Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add allRefs = true argument to fetchGit to explicitly perform a full checkout #3814

Merged
merged 4 commits into from Dec 22, 2020

Conversation

Ma27
Copy link
Member

@Ma27 Ma27 commented Jul 14, 2020

Sometimes it's needed to fetch the revision of a git repository without knowing the specific ref. In those cases it's needed to perform a full checkout which is now possible by declaring builtins.fetchGit { allRefs = true; /* url, rev, etc */ }.

Refs #2431 #2409

For further details, please read the descriptions of the two commits.

cc @edolstra

@bjornfor
Copy link
Contributor

Git clone fetches all branches by default, that's why I think fetchGit should do the same, by simply omitting the ref argument.

@Ma27
Copy link
Member Author

Ma27 commented Jul 14, 2020

Well, we're not cloning a git repo though, only the specified ref (or master as fallback) is fetched using git fetch. That's the entire problem behind this :)

@Ma27
Copy link
Member Author

Ma27 commented Jul 14, 2020

Also, I think it's fine to fetch master only by default: unless you need it, you shouldn't have to fetch a full repo.

src/libfetchers/git.cc Outdated Show resolved Hide resolved
@bjornfor
Copy link
Contributor

Well, we're not cloning a git repo though, only the specified ref (or master as fallback) is fetched using git fetch. That's the entire problem behind this :)

I know, but instead of falling back to master we could fall back to "all". IMHO that's more natural, because git clone URL can be translated more directly tofetchGit { URL } (less new things to learn).

@Ma27
Copy link
Member Author

Ma27 commented Jul 15, 2020

@bjornfor I agree with @edolstra's reasoning in #2431 (comment). This should just be an escape-hatch if you really need it.

@Ma27 Ma27 force-pushed the git-rev-error branch 2 times, most recently from f49c707 to 9cdd68e Compare July 17, 2020 18:43
@Ma27
Copy link
Member Author

Ma27 commented Jul 17, 2020

Rebased onto latest master.

@Ma27
Copy link
Member Author

Ma27 commented Jul 26, 2020

@edolstra would you be fine with the overall approach taken here to work around the usability-issues of fetchGit?

@Ma27
Copy link
Member Author

Ma27 commented Jul 29, 2020

Rebased onto master now.

@Ma27
Copy link
Member Author

Ma27 commented Aug 10, 2020

cc @edolstra would you mind taking a look at this? :)

@Ma27
Copy link
Member Author

Ma27 commented Sep 8, 2020

@edolstra @domenkozar rebased onto latest master. Would you mind taking a look? :)

@Ma27
Copy link
Member Author

Ma27 commented Sep 27, 2020

@edolstra is there anything missing in this PR? :)

src/libfetchers/git.cc Outdated Show resolved Hide resolved
@edolstra
Copy link
Member

For backwards compatibility, instead of adding an allRefs argument, we could also bring back ref = "*".

BTW, when using this, what ref gets stored in lock files?

@Ma27
Copy link
Member Author

Ma27 commented Sep 29, 2020

For backwards compatibility, instead of adding an allRefs argument, we could also bring back ref = "*".

Unfortunately I don't remember the exact details why I decided to create a new attribute, but I think that this was to avoid doing even more magic with ref (we already check if it starts with refs/ etc.).

However I just realized that we'd have to use a string anyways to get this working as flake input (unless we alter the logic in libexpr, see below in this comment). So @edolstra it's up to you what you'd prefer, I guess I'd be fine with both variants.

BTW, when using this, what ref gets stored in lock files?

None as I just realized that using this as flake-input doesn't even evaluate (only tested with fetchGit here, sorry!).

The reason is that flake-attrs can't seem to be a boolean:

if (attr.value->type == tString)
attrs.emplace(attr.name, attr.value->string.s);
else
throw TypeError("flake input attribute '%s' is %s while a string is expected",
attr.name, showType(*attr.value));

@Ma27
Copy link
Member Author

Ma27 commented Oct 2, 2020

ping @edolstra how shall we proceed here? :)

@Ma27
Copy link
Member Author

Ma27 commented Oct 9, 2020

ping @edolstra

@edolstra
Copy link
Member

edolstra commented Oct 9, 2020

The reason is that flake-attrs can't seem to be a boolean:

We can just handle booleans there. The only reason they're not implemented is because there was no need at the time.

@Ma27
Copy link
Member Author

Ma27 commented Oct 9, 2020

...which means that the current approach is fine?

@Ma27
Copy link
Member Author

Ma27 commented Oct 28, 2020

cc @edolstra anything else tbd here now? :)

@Ma27
Copy link
Member Author

Ma27 commented Nov 8, 2020

@edolstra is the current change fine now?

@Ma27
Copy link
Member Author

Ma27 commented Nov 15, 2020

cc @edolstra anything tbd here? :)

@Ma27
Copy link
Member Author

Ma27 commented Nov 29, 2020

cc @edolstra can we merge this?


auto result = runProgram(checkCommitOpts);
if (WEXITSTATUS(result.first) == 128
&& result.second.find("bad file") != std::string::npos
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking for strings like "bad file" in stderr seems pretty fragile... Do we actually need this test? Presumably a wrong rev will fail in the subsequent call to git archive.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid no: if git cat-file errors, the exit code is always 128, the reason for the error is on stderr.

…revision can't be checked out

A common pitfall when using e.g. `builtins.fetchGit` is the `fatal: not
a tree object`-error when trying to fetch a revision of a git-repository
that isn't on the `master` branch and no `ref` is specified.

In order to make clear what's the problem, I added a simple check
whether the revision in question exists and if it doesn't a more
meaningful error-message is displayed:

```
nix-repl> builtins.fetchGit { url = "https://github.com/owner/myrepo"; rev = "<commit not on master>"; }
moderror: --- Error -------------------------------------------------------------------- nix
Cannot find Git revision 'bf1cc5c648e6aed7360448a3745bb2fe4fbbf0e9' in ref 'master' of repository 'https://gitlab.com/Ma27/nvim.nix'! Please make sure that the rev exists on the ref you've specified or add allRefs = true; to fetchGit.
```

Closes NixOS#2431
Sometimes it's necessary to fetch a git repository at a revision and
it's unknown which ref contains the revision in question. An example
would be a Cargo.lock which only provides the URL and the revision when
using a git repository as build input.

However it's considered a bad practice to perform a full checkout of a
repository since this may take a lot of time and can eat up a lot of
disk space. This patch makes a full checkout explicit by adding an
`allRefs` argument to `builtins.fetchGit` which fetches all refs if
explicitly set to true.

Closes NixOS#2409
@Ma27
Copy link
Member Author

Ma27 commented Dec 22, 2020

@edolstra rebased, fixed the docs and also added a test :)

@edolstra edolstra merged commit f4a9fb6 into NixOS:master Dec 22, 2020
@edolstra
Copy link
Member

Thanks, merged!

@AleXoundOS
Copy link

I know, but instead of falling back to master we could fall back to "all".

Originally I thought so too. But in practice this could leave missing commits in master branch unnoticed, until a feature branch gets deleted on remote.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants