2020-04-08 15:12:22 +03:00
|
|
|
#include "filetransfer.hh"
|
2020-03-30 17:04:18 +03:00
|
|
|
#include "cache.hh"
|
|
|
|
#include "globals.hh"
|
|
|
|
#include "store-api.hh"
|
2020-06-17 22:08:59 +03:00
|
|
|
#include "types.hh"
|
2020-09-21 19:22:45 +03:00
|
|
|
#include "url-parts.hh"
|
2022-05-04 15:32:21 +03:00
|
|
|
#include "git.hh"
|
2022-03-01 03:29:34 +02:00
|
|
|
#include "fetchers.hh"
|
|
|
|
#include "fetch-settings.hh"
|
|
|
|
|
2020-09-25 08:49:44 +03:00
|
|
|
#include <optional>
|
2020-03-30 17:04:18 +03:00
|
|
|
#include <nlohmann/json.hpp>
|
2021-10-06 19:32:46 +03:00
|
|
|
#include <fstream>
|
2020-03-30 17:04:18 +03:00
|
|
|
|
|
|
|
namespace nix::fetchers {
|
|
|
|
|
2020-06-17 22:08:59 +03:00
|
|
|
struct DownloadUrl
|
|
|
|
{
|
|
|
|
std::string url;
|
2020-09-25 08:49:44 +03:00
|
|
|
Headers headers;
|
2020-06-17 22:08:59 +03:00
|
|
|
};
|
|
|
|
|
2021-10-06 19:32:46 +03:00
|
|
|
// A github, gitlab, or sourcehut host
|
2020-09-21 17:29:08 +03:00
|
|
|
const static std::string hostRegexS = "[a-zA-Z0-9.]*"; // FIXME: check
|
|
|
|
std::regex hostRegex(hostRegexS, std::regex::ECMAScript);
|
2020-03-30 17:04:18 +03:00
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
struct GitArchiveInputScheme : InputScheme
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
2022-12-07 13:58:58 +02:00
|
|
|
virtual std::string type() const = 0;
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2020-10-06 15:00:42 +03:00
|
|
|
virtual std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const = 0;
|
2020-06-17 22:08:59 +03:00
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
std::optional<Input> inputFromURL(const ParsedURL & url) const override
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
if (url.scheme != type()) return {};
|
|
|
|
|
|
|
|
auto path = tokenizeString<std::vector<std::string>>(url.path, "/");
|
|
|
|
|
|
|
|
std::optional<Hash> rev;
|
|
|
|
std::optional<std::string> ref;
|
2020-06-04 14:36:30 +03:00
|
|
|
std::optional<std::string> host_url;
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
|
2020-10-06 21:08:51 +03:00
|
|
|
auto size = path.size();
|
|
|
|
if (size == 3) {
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
if (std::regex_match(path[2], revRegex))
|
2020-07-16 20:28:52 +03:00
|
|
|
rev = Hash::parseAny(path[2], htSHA1);
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
else if (std::regex_match(path[2], refRegex))
|
|
|
|
ref = path[2];
|
|
|
|
else
|
|
|
|
throw BadURL("in URL '%s', '%s' is not a commit hash or branch/tag name", url.url, path[2]);
|
2020-10-06 21:08:51 +03:00
|
|
|
} else if (size > 3) {
|
|
|
|
std::string rs;
|
|
|
|
for (auto i = std::next(path.begin(), 2); i != path.end(); i++) {
|
|
|
|
rs += *i;
|
|
|
|
if (std::next(i) != path.end()) {
|
|
|
|
rs += "/";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::regex_match(rs, refRegex)) {
|
|
|
|
ref = rs;
|
|
|
|
} else {
|
|
|
|
throw BadURL("in URL '%s', '%s' is not a branch/tag name", url.url, rs);
|
|
|
|
}
|
|
|
|
} else if (size < 2)
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
throw BadURL("URL '%s' is invalid", url.url);
|
|
|
|
|
|
|
|
for (auto &[name, value] : url.query) {
|
|
|
|
if (name == "rev") {
|
|
|
|
if (rev)
|
|
|
|
throw BadURL("URL '%s' contains multiple commit hashes", url.url);
|
2020-07-16 20:28:52 +03:00
|
|
|
rev = Hash::parseAny(value, htSHA1);
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
}
|
|
|
|
else if (name == "ref") {
|
|
|
|
if (!std::regex_match(value, refRegex))
|
|
|
|
throw BadURL("URL '%s' contains an invalid branch/tag name", url.url);
|
|
|
|
if (ref)
|
|
|
|
throw BadURL("URL '%s' contains multiple branch/tag names", url.url);
|
|
|
|
ref = value;
|
|
|
|
}
|
2020-09-25 08:46:03 +03:00
|
|
|
else if (name == "host") {
|
2020-09-21 17:29:08 +03:00
|
|
|
if (!std::regex_match(value, hostRegex))
|
2020-09-25 08:46:03 +03:00
|
|
|
throw BadURL("URL '%s' contains an invalid instance host", url.url);
|
2020-06-04 14:36:30 +03:00
|
|
|
host_url = value;
|
|
|
|
}
|
2020-05-30 01:59:13 +03:00
|
|
|
// FIXME: barf on unsupported attributes
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ref && rev)
|
2020-06-09 14:45:07 +03:00
|
|
|
throw BadURL("URL '%s' contains both a commit hash and a branch/tag name %s %s", url.url, *ref, rev->gitRev());
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
|
|
|
|
Input input;
|
|
|
|
input.attrs.insert_or_assign("type", type());
|
|
|
|
input.attrs.insert_or_assign("owner", path[0]);
|
|
|
|
input.attrs.insert_or_assign("repo", path[1]);
|
|
|
|
if (rev) input.attrs.insert_or_assign("rev", rev->gitRev());
|
|
|
|
if (ref) input.attrs.insert_or_assign("ref", *ref);
|
2020-09-25 08:46:03 +03:00
|
|
|
if (host_url) input.attrs.insert_or_assign("host", *host_url);
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
|
|
|
|
return input;
|
2020-03-30 17:04:18 +03:00
|
|
|
}
|
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
std::optional<Input> inputFromAttrs(const Attrs & attrs) const override
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
if (maybeGetStrAttr(attrs, "type") != type()) return {};
|
2020-01-21 17:27:53 +02:00
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
for (auto & [name, value] : attrs)
|
2020-09-25 08:46:03 +03:00
|
|
|
if (name != "type" && name != "owner" && name != "repo" && name != "ref" && name != "rev" && name != "narHash" && name != "lastModified" && name != "host")
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
throw Error("unsupported input attribute '%s'", name);
|
2020-03-30 17:04:18 +03:00
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
getStrAttr(attrs, "owner");
|
|
|
|
getStrAttr(attrs, "repo");
|
2020-03-30 17:04:18 +03:00
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
Input input;
|
|
|
|
input.attrs = attrs;
|
|
|
|
return input;
|
|
|
|
}
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
ParsedURL toURL(const Input & input) const override
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
auto owner = getStrAttr(input.attrs, "owner");
|
|
|
|
auto repo = getStrAttr(input.attrs, "repo");
|
|
|
|
auto ref = input.getRef();
|
|
|
|
auto rev = input.getRev();
|
2020-03-30 17:04:18 +03:00
|
|
|
auto path = owner + "/" + repo;
|
|
|
|
assert(!(ref && rev));
|
|
|
|
if (ref) path += "/" + *ref;
|
|
|
|
if (rev) path += "/" + rev->to_string(Base16, false);
|
|
|
|
return ParsedURL {
|
2020-05-29 15:23:32 +03:00
|
|
|
.scheme = type(),
|
2020-03-30 17:04:18 +03:00
|
|
|
.path = path,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
bool hasAllInfo(const Input & input) const override
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
return input.getRev() && maybeGetIntAttr(input.attrs, "lastModified");
|
2020-03-30 17:04:18 +03:00
|
|
|
}
|
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
Input applyOverrides(
|
|
|
|
const Input & _input,
|
|
|
|
std::optional<std::string> ref,
|
2022-12-07 13:58:58 +02:00
|
|
|
std::optional<Hash> rev) const override
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
auto input(_input);
|
2020-06-09 14:45:07 +03:00
|
|
|
if (rev && ref)
|
|
|
|
throw BadURL("cannot apply both a commit hash (%s) and a branch/tag name ('%s') to input '%s'",
|
|
|
|
rev->gitRev(), *ref, input.to_string());
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
if (rev) {
|
|
|
|
input.attrs.insert_or_assign("rev", rev->gitRev());
|
|
|
|
input.attrs.erase("ref");
|
2020-03-30 17:04:18 +03:00
|
|
|
}
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
if (ref) {
|
|
|
|
input.attrs.insert_or_assign("ref", *ref);
|
2020-06-09 14:45:07 +03:00
|
|
|
input.attrs.erase("rev");
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
}
|
|
|
|
return input;
|
2020-01-31 20:16:40 +02:00
|
|
|
}
|
|
|
|
|
2020-09-30 13:11:22 +03:00
|
|
|
std::optional<std::string> getAccessToken(const std::string & host) const
|
|
|
|
{
|
2022-03-01 03:29:34 +02:00
|
|
|
auto tokens = fetchSettings.accessTokens.get();
|
2020-09-30 13:11:22 +03:00
|
|
|
if (auto token = get(tokens, host))
|
|
|
|
return *token;
|
|
|
|
return {};
|
2020-09-25 08:49:44 +03:00
|
|
|
}
|
|
|
|
|
2020-09-30 13:11:22 +03:00
|
|
|
Headers makeHeadersWithAuthTokens(const std::string & host) const
|
|
|
|
{
|
2020-09-25 08:49:44 +03:00
|
|
|
Headers headers;
|
|
|
|
auto accessToken = getAccessToken(host);
|
|
|
|
if (accessToken) {
|
|
|
|
auto hdr = accessHeaderFromToken(*accessToken);
|
|
|
|
if (hdr)
|
|
|
|
headers.push_back(*hdr);
|
|
|
|
else
|
|
|
|
warn("Unrecognized access token for host '%s'", host);
|
|
|
|
}
|
|
|
|
return headers;
|
|
|
|
}
|
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
virtual Hash getRevFromRef(nix::ref<Store> store, const Input & input) const = 0;
|
2020-05-29 15:23:32 +03:00
|
|
|
|
2020-06-17 22:08:59 +03:00
|
|
|
virtual DownloadUrl getDownloadUrl(const Input & input) const = 0;
|
2020-01-21 17:27:53 +02:00
|
|
|
|
2022-02-15 15:33:31 +02:00
|
|
|
std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
|
2020-01-21 17:27:53 +02:00
|
|
|
{
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
Input input(_input);
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2020-06-18 14:25:08 +03:00
|
|
|
if (!maybeGetStrAttr(input.attrs, "ref")) input.attrs.insert_or_assign("ref", "HEAD");
|
2020-01-21 17:27:53 +02:00
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
auto rev = input.getRev();
|
|
|
|
if (!rev) rev = getRevFromRef(store, input);
|
|
|
|
|
|
|
|
input.attrs.erase("ref");
|
|
|
|
input.attrs.insert_or_assign("rev", rev->gitRev());
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2022-02-24 19:09:00 +02:00
|
|
|
Attrs lockedAttrs({
|
2020-03-30 17:04:18 +03:00
|
|
|
{"type", "git-tarball"},
|
|
|
|
{"rev", rev->gitRev()},
|
|
|
|
});
|
|
|
|
|
2022-02-24 19:09:00 +02:00
|
|
|
if (auto res = getCache()->lookup(store, lockedAttrs)) {
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
input.attrs.insert_or_assign("lastModified", getIntAttr(res->first, "lastModified"));
|
2022-02-15 15:33:31 +02:00
|
|
|
return {std::move(res->second), input};
|
2020-03-30 17:04:18 +03:00
|
|
|
}
|
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
auto url = getDownloadUrl(input);
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2021-07-06 09:43:19 +03:00
|
|
|
auto [tree, lastModified] = downloadTarball(store, url.url, input.getName(), true, url.headers);
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2021-04-09 14:51:57 +03:00
|
|
|
input.attrs.insert_or_assign("lastModified", uint64_t(lastModified));
|
2020-03-30 17:04:18 +03:00
|
|
|
|
|
|
|
getCache()->add(
|
|
|
|
store,
|
2022-02-24 19:09:00 +02:00
|
|
|
lockedAttrs,
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
|
|
|
{"rev", rev->gitRev()},
|
2021-04-09 14:51:57 +03:00
|
|
|
{"lastModified", uint64_t(lastModified)}
|
2020-03-30 17:04:18 +03:00
|
|
|
},
|
|
|
|
tree.storePath,
|
|
|
|
true);
|
|
|
|
|
2022-02-15 15:33:31 +02:00
|
|
|
return {std::move(tree.storePath), input};
|
2020-03-30 17:04:18 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
struct GitHubInputScheme : GitArchiveInputScheme
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
2022-12-07 13:58:58 +02:00
|
|
|
std::string type() const override { return "github"; }
|
2020-05-29 15:23:32 +03:00
|
|
|
|
2020-10-06 15:00:42 +03:00
|
|
|
std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const override
|
2020-09-30 13:11:22 +03:00
|
|
|
{
|
2020-09-25 08:49:44 +03:00
|
|
|
// Github supports PAT/OAuth2 tokens and HTTP Basic
|
|
|
|
// Authentication. The former simply specifies the token, the
|
|
|
|
// latter can use the token as the password. Only the first
|
|
|
|
// is used here. See
|
|
|
|
// https://developer.github.com/v3/#authentication and
|
|
|
|
// https://docs.github.com/en/developers/apps/authorizing-oath-apps
|
2020-06-17 22:08:59 +03:00
|
|
|
return std::pair<std::string, std::string>("Authorization", fmt("token %s", token));
|
2020-09-01 16:29:04 +03:00
|
|
|
}
|
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
std::string getHost(const Input & input) const
|
|
|
|
{
|
|
|
|
return maybeGetStrAttr(input.attrs, "host").value_or("github.com");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string getOwner(const Input & input) const
|
|
|
|
{
|
|
|
|
return getStrAttr(input.attrs, "owner");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string getRepo(const Input & input) const
|
|
|
|
{
|
|
|
|
return getStrAttr(input.attrs, "repo");
|
|
|
|
}
|
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
Hash getRevFromRef(nix::ref<Store> store, const Input & input) const override
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
2022-12-07 13:58:58 +02:00
|
|
|
auto host = getHost(input);
|
2022-05-05 20:46:48 +03:00
|
|
|
auto url = fmt(
|
|
|
|
host == "github.com"
|
|
|
|
? "https://api.%s/repos/%s/%s/commits/%s"
|
|
|
|
: "https://%s/api/v3/repos/%s/%s/commits/%s",
|
2022-12-07 13:58:58 +02:00
|
|
|
host, getOwner(input), getRepo(input), *input.getRef());
|
2020-09-01 16:29:04 +03:00
|
|
|
|
2020-09-25 08:49:44 +03:00
|
|
|
Headers headers = makeHeadersWithAuthTokens(host);
|
2020-09-01 16:29:04 +03:00
|
|
|
|
2020-05-29 15:23:32 +03:00
|
|
|
auto json = nlohmann::json::parse(
|
|
|
|
readFile(
|
|
|
|
store->toRealPath(
|
2020-09-29 14:05:19 +03:00
|
|
|
downloadFile(store, url, "source", false, headers).storePath)));
|
2020-07-16 20:28:52 +03:00
|
|
|
auto rev = Hash::parseAny(std::string { json["sha"] }, htSHA1);
|
2020-05-29 15:23:32 +03:00
|
|
|
debug("HEAD revision for '%s' is %s", url, rev.gitRev());
|
|
|
|
return rev;
|
|
|
|
}
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2020-06-17 22:08:59 +03:00
|
|
|
DownloadUrl getDownloadUrl(const Input & input) const override
|
2020-05-29 15:23:32 +03:00
|
|
|
{
|
2022-12-07 13:58:58 +02:00
|
|
|
auto host = getHost(input);
|
|
|
|
|
2022-09-12 23:50:18 +03:00
|
|
|
Headers headers = makeHeadersWithAuthTokens(host);
|
2022-12-07 13:58:58 +02:00
|
|
|
|
2022-09-12 23:50:18 +03:00
|
|
|
// If we have no auth headers then we default to the public archive
|
|
|
|
// urls so we do not run into rate limits.
|
|
|
|
const auto urlFmt =
|
|
|
|
host != "github.com"
|
|
|
|
? "https://%s/api/v3/repos/%s/%s/tarball/%s"
|
|
|
|
: headers.empty()
|
|
|
|
? "https://%s/%s/%s/archive/%s.tar.gz"
|
|
|
|
: "https://api.%s/repos/%s/%s/tarball/%s";
|
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
const auto url = fmt(urlFmt, host, getOwner(input), getRepo(input),
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
input.getRev()->to_string(Base16, false));
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2020-09-30 13:09:18 +03:00
|
|
|
return DownloadUrl { url, headers };
|
2020-05-29 15:23:32 +03:00
|
|
|
}
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
void clone(const Input & input, const Path & destDir) const override
|
2020-05-29 15:23:32 +03:00
|
|
|
{
|
2022-12-07 13:58:58 +02:00
|
|
|
auto host = getHost(input);
|
2021-09-14 14:38:05 +03:00
|
|
|
Input::fromURL(fmt("git+https://%s/%s/%s.git",
|
2022-12-07 13:58:58 +02:00
|
|
|
host, getOwner(input), getRepo(input)))
|
2021-09-14 14:38:45 +03:00
|
|
|
.applyOverrides(input.getRef(), input.getRev())
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
.clone(destDir);
|
2020-05-29 15:23:32 +03:00
|
|
|
}
|
|
|
|
};
|
2020-03-30 17:04:18 +03:00
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
struct GitLabInputScheme : GitArchiveInputScheme
|
2020-05-29 15:23:32 +03:00
|
|
|
{
|
2022-12-07 13:58:58 +02:00
|
|
|
std::string type() const override { return "gitlab"; }
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2020-10-06 15:00:42 +03:00
|
|
|
std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const override
|
2020-09-30 13:11:22 +03:00
|
|
|
{
|
2020-09-25 08:49:44 +03:00
|
|
|
// Gitlab supports 4 kinds of authorization, two of which are
|
|
|
|
// relevant here: OAuth2 and PAT (Private Access Token). The
|
|
|
|
// user can indicate which token is used by specifying the
|
|
|
|
// token as <TYPE>:<VALUE>, where type is "OAuth2" or "PAT".
|
|
|
|
// If the <TYPE> is unrecognized, this will fall back to
|
|
|
|
// treating this simply has <HDRNAME>:<HDRVAL>. See
|
|
|
|
// https://docs.gitlab.com/12.10/ee/api/README.html#authentication
|
|
|
|
auto fldsplit = token.find_first_of(':');
|
|
|
|
// n.b. C++20 would allow: if (token.starts_with("OAuth2:")) ...
|
|
|
|
if ("OAuth2" == token.substr(0, fldsplit))
|
|
|
|
return std::make_pair("Authorization", fmt("Bearer %s", token.substr(fldsplit+1)));
|
|
|
|
if ("PAT" == token.substr(0, fldsplit))
|
|
|
|
return std::make_pair("Private-token", token.substr(fldsplit+1));
|
|
|
|
warn("Unrecognized GitLab token type %s", token.substr(0, fldsplit));
|
2021-11-14 13:23:46 +02:00
|
|
|
return std::make_pair(token.substr(0,fldsplit), token.substr(fldsplit+1));
|
2020-06-17 22:08:59 +03:00
|
|
|
}
|
|
|
|
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
Hash getRevFromRef(nix::ref<Store> store, const Input & input) const override
|
2020-05-29 15:23:32 +03:00
|
|
|
{
|
2020-09-25 08:49:44 +03:00
|
|
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
|
|
|
// See rate limiting note below
|
2020-07-13 20:22:59 +03:00
|
|
|
auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/commits?ref_name=%s",
|
2020-09-25 08:49:44 +03:00
|
|
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"), *input.getRef());
|
2020-06-17 22:08:59 +03:00
|
|
|
|
2020-09-25 08:49:44 +03:00
|
|
|
Headers headers = makeHeadersWithAuthTokens(host);
|
2020-06-17 22:08:59 +03:00
|
|
|
|
2020-05-29 15:23:32 +03:00
|
|
|
auto json = nlohmann::json::parse(
|
|
|
|
readFile(
|
|
|
|
store->toRealPath(
|
2020-09-29 14:05:19 +03:00
|
|
|
downloadFile(store, url, "source", false, headers).storePath)));
|
2020-07-16 20:28:52 +03:00
|
|
|
auto rev = Hash::parseAny(std::string(json[0]["id"]), htSHA1);
|
2020-05-29 15:23:32 +03:00
|
|
|
debug("HEAD revision for '%s' is %s", url, rev.gitRev());
|
|
|
|
return rev;
|
2020-03-30 17:04:18 +03:00
|
|
|
}
|
|
|
|
|
2020-06-17 22:08:59 +03:00
|
|
|
DownloadUrl getDownloadUrl(const Input & input) const override
|
2020-03-30 17:04:18 +03:00
|
|
|
{
|
2020-09-25 08:46:03 +03:00
|
|
|
// This endpoint has a rate limit threshold that may be
|
|
|
|
// server-specific and vary based whether the user is
|
|
|
|
// authenticated via an accessToken or not, but the usual rate
|
|
|
|
// is 10 reqs/sec/ip-addr. See
|
|
|
|
// https://docs.gitlab.com/ee/user/gitlab_com/index.html#gitlabcom-specific-rate-limits
|
|
|
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
2020-06-04 14:36:30 +03:00
|
|
|
auto url = fmt("https://%s/api/v4/projects/%s%%2F%s/repository/archive.tar.gz?sha=%s",
|
2020-09-25 08:46:03 +03:00
|
|
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
input.getRev()->to_string(Base16, false));
|
2020-03-30 17:04:18 +03:00
|
|
|
|
2020-09-25 08:49:44 +03:00
|
|
|
Headers headers = makeHeadersWithAuthTokens(host);
|
2020-09-30 13:09:18 +03:00
|
|
|
return DownloadUrl { url, headers };
|
2020-05-29 15:23:32 +03:00
|
|
|
}
|
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
void clone(const Input & input, const Path & destDir) const override
|
2020-05-29 15:23:32 +03:00
|
|
|
{
|
2020-09-25 08:46:03 +03:00
|
|
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
2020-06-04 14:36:30 +03:00
|
|
|
// FIXME: get username somewhere
|
2021-09-14 23:53:31 +03:00
|
|
|
Input::fromURL(fmt("git+https://%s/%s/%s.git",
|
2020-09-25 08:46:03 +03:00
|
|
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
2021-09-14 14:38:45 +03:00
|
|
|
.applyOverrides(input.getRef(), input.getRev())
|
Remove TreeInfo
The attributes previously stored in TreeInfo (narHash, revCount,
lastModified) are now stored in Input. This makes it less arbitrary
what attributes are stored where.
As a result, the lock file format has changed. An entry like
"info": {
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github"
},
is now stored as
"locked": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b88ff468e9850410070d4e0ccd68c7011f15b2be",
"type": "github",
"lastModified": 1585405475,
"narHash": "sha256-bESW0n4KgPmZ0luxvwJ+UyATrC6iIltVCsGdLiphVeE="
},
The 'Input' class is now a dumb set of attributes. All the fetcher
implementations subclass InputScheme, not Input. This simplifies the
API.
Also, fix substitution of flake inputs. This was broken since lazy
flake fetching started using fetchTree internally.
2020-05-30 01:44:11 +03:00
|
|
|
.clone(destDir);
|
2020-03-30 17:04:18 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-10-06 19:32:46 +03:00
|
|
|
struct SourceHutInputScheme : GitArchiveInputScheme
|
|
|
|
{
|
2022-12-07 13:58:58 +02:00
|
|
|
std::string type() const override { return "sourcehut"; }
|
2021-10-06 19:32:46 +03:00
|
|
|
|
|
|
|
std::optional<std::pair<std::string, std::string>> accessHeaderFromToken(const std::string & token) const override
|
|
|
|
{
|
|
|
|
// SourceHut supports both PAT and OAuth2. See
|
|
|
|
// https://man.sr.ht/meta.sr.ht/oauth.md
|
|
|
|
return std::pair<std::string, std::string>("Authorization", fmt("Bearer %s", token));
|
|
|
|
// Note: This currently serves no purpose, as this kind of authorization
|
|
|
|
// does not allow for downloading tarballs on sourcehut private repos.
|
|
|
|
// Once it is implemented, however, should work as expected.
|
|
|
|
}
|
|
|
|
|
|
|
|
Hash getRevFromRef(nix::ref<Store> store, const Input & input) const override
|
|
|
|
{
|
|
|
|
// TODO: In the future, when the sourcehut graphql API is implemented for mercurial
|
|
|
|
// and with anonymous access, this method should use it instead.
|
|
|
|
|
|
|
|
auto ref = *input.getRef();
|
|
|
|
|
|
|
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
|
|
|
auto base_url = fmt("https://%s/%s/%s",
|
|
|
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"));
|
|
|
|
|
|
|
|
Headers headers = makeHeadersWithAuthTokens(host);
|
|
|
|
|
2022-06-11 22:52:20 +03:00
|
|
|
std::string refUri;
|
2021-10-06 19:32:46 +03:00
|
|
|
if (ref == "HEAD") {
|
|
|
|
auto file = store->toRealPath(
|
|
|
|
downloadFile(store, fmt("%s/HEAD", base_url), "source", false, headers).storePath);
|
|
|
|
std::ifstream is(file);
|
|
|
|
std::string line;
|
|
|
|
getline(is, line);
|
|
|
|
|
2022-05-04 15:32:21 +03:00
|
|
|
auto remoteLine = git::parseLsRemoteLine(line);
|
|
|
|
if (!remoteLine) {
|
2021-10-06 19:32:46 +03:00
|
|
|
throw BadURL("in '%d', couldn't resolve HEAD ref '%d'", input.to_string(), ref);
|
|
|
|
}
|
2022-06-11 22:52:20 +03:00
|
|
|
refUri = remoteLine->target;
|
2022-04-30 01:30:00 +03:00
|
|
|
} else {
|
2022-06-11 22:52:20 +03:00
|
|
|
refUri = fmt("refs/(heads|tags)/%s", ref);
|
2022-04-30 01:30:00 +03:00
|
|
|
}
|
2022-06-11 22:52:20 +03:00
|
|
|
std::regex refRegex(refUri);
|
2021-10-06 19:32:46 +03:00
|
|
|
|
|
|
|
auto file = store->toRealPath(
|
|
|
|
downloadFile(store, fmt("%s/info/refs", base_url), "source", false, headers).storePath);
|
|
|
|
std::ifstream is(file);
|
|
|
|
|
|
|
|
std::string line;
|
2022-04-30 01:30:00 +03:00
|
|
|
std::optional<std::string> id;
|
|
|
|
while(!id && getline(is, line)) {
|
2022-05-04 15:32:21 +03:00
|
|
|
auto parsedLine = git::parseLsRemoteLine(line);
|
2022-06-11 22:52:20 +03:00
|
|
|
if (parsedLine && parsedLine->reference && std::regex_match(*parsedLine->reference, refRegex))
|
2022-05-04 15:32:21 +03:00
|
|
|
id = parsedLine->target;
|
2021-10-06 19:32:46 +03:00
|
|
|
}
|
|
|
|
|
2022-04-30 01:30:00 +03:00
|
|
|
if(!id)
|
2021-10-06 19:32:46 +03:00
|
|
|
throw BadURL("in '%d', couldn't find ref '%d'", input.to_string(), ref);
|
|
|
|
|
2022-04-30 01:30:00 +03:00
|
|
|
auto rev = Hash::parseAny(*id, htSHA1);
|
2021-10-06 19:32:46 +03:00
|
|
|
debug("HEAD revision for '%s' is %s", fmt("%s/%s", base_url, ref), rev.gitRev());
|
|
|
|
return rev;
|
|
|
|
}
|
|
|
|
|
|
|
|
DownloadUrl getDownloadUrl(const Input & input) const override
|
|
|
|
{
|
|
|
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
|
|
|
auto url = fmt("https://%s/%s/%s/archive/%s.tar.gz",
|
|
|
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo"),
|
|
|
|
input.getRev()->to_string(Base16, false));
|
|
|
|
|
|
|
|
Headers headers = makeHeadersWithAuthTokens(host);
|
|
|
|
return DownloadUrl { url, headers };
|
|
|
|
}
|
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
void clone(const Input & input, const Path & destDir) const override
|
2021-10-06 19:32:46 +03:00
|
|
|
{
|
|
|
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
|
|
|
Input::fromURL(fmt("git+https://%s/%s/%s",
|
|
|
|
host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
|
|
|
.applyOverrides(input.getRef(), input.getRev())
|
|
|
|
.clone(destDir);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-10-06 14:36:55 +03:00
|
|
|
static auto rGitHubInputScheme = OnStartup([] { registerInputScheme(std::make_unique<GitHubInputScheme>()); });
|
|
|
|
static auto rGitLabInputScheme = OnStartup([] { registerInputScheme(std::make_unique<GitLabInputScheme>()); });
|
2021-10-06 19:32:46 +03:00
|
|
|
static auto rSourceHutInputScheme = OnStartup([] { registerInputScheme(std::make_unique<SourceHutInputScheme>()); });
|
2020-03-30 17:04:18 +03:00
|
|
|
|
|
|
|
}
|