-
-
Couldn't load subscription status.
- Fork 960
Ask git where its daemon is and use that #1697
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
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm uneasy about having the test suite call the nonpublic
_call_processmethod to do this. I want it to use the samegitas GitPython uses, including the effect of theGIT_PYTHON_GIT_EXECUTABLE(as well as any future nuances that might ever arise) automatically, whichGit().execute(["git", "--exec-path"])would not do. If the command weregit exec-pathorgit something --exec-path, then I thinkGit().exec_path()orGit.something(exec_path=True), respectively, could be used. But for agitcommand that has no subcommand and just passes an option, I don't know of a way to use GitPython's public interface to run it. It may be that I'm just missing something obvious here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's definitely a shortcoming in the
Gitclass' API, it does always assume a sub-command. This also makes it impossible to set configuration overrides, for instance, so finding a solution for this will have immediate benefits, and it would definitely be welcome.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the main hard part of adding such functionality is figuring out a way to do it that wouldn't be a breaking change. Most ordinary public-style method names could clash with someone's custom
gitcommands (such as scripts named likegit-*), which GitPython is generally able to run and thus would begin to break after such a change. The most intuitive names for this, likeinvoke, would be especially likely to clash (I'm sure some people have agit-invokescript).Is this because only one
-ccan be passed by calling theGitinstance withc=..., or for some other reason (or am I misunderstanding what you mean)? To use an example inspired bycheck-version.sh, and withgas agit.cmd.Gitinstance, I can cause-c versionsort.suffix=-preto be passed, and in the correct position, with:That runs
git -c versionsort.suffix=-pre tag --sort=-v:refnameas desired, with-c versionsort.suffix=-prebefore the subcommand name and--sort=-v:refnamefollowing it.However, I can't pass more than one
-cthat way, because a single call can't pass the same keyword argument multiple times, and the preceding arguments are discarded with multiple calls, i.e., these do the same thing:But I'm not sure this is the problem you're thinking of, because a solution for passing
-carguments and their operands, or for passing arbitrary arguments before a subcommand, would not necessarily facilitate runninggitwithout a subcommand. Nor would a solution for runninggitwithout a subcommand necessarily allow a subcommand to be added in a user-friendly way supporting the keyword argument syntax for specifying the subcommand's own flags.Can people just use
_call_process?For having GitPython run
gitwith arbitrarily specified arguments, the nonpublic_call_processmethod does that. Does its behavior differ from the desired behavior for doing so?If not, then that method could be made public simply by documenting it as public, which would avoid breaking any custom
gitcommands, because (a) it wouldn't change the actual behavior of GitPython at all, and (b) GitPython already doesn't support customgitcommands that start with_, andgititself doesn't support custom commands that start with-(since an attempt to invoke such a command would pass one or more options instead).An example of where an attribute with a leading
_that is made public by documenting it as public, for the same reasons as we might want to do so here--that any other name might clash--is how types constructed with thecollections.namedtuplefactory have public_make,_asdict,_replace,_fields, and_field_defaultsattributes. (In contrast, although the_threadmodule is public, this is not really an example of this, because it is not named that way for a similar reason.)On the other hand, there may be some reasons not to make
_call_processpublic by declaring it so. The interface forcollections.namedtupleis simpler than forgit.cmd.Git, and also more widely known about because it is part of the standard library, so deviations from common naming conventions may be more discoverable. Also, intuitively, even if_call_processwere public, its name suggests that its use from outside GitPython's own code would be rarer thanexecute. But using aGitobject to run a non-gitcommand should be rare, so if_call_processis public then it should be used more often thanexecute.Making a "submethod" to run
gitwith literal argumentsOne possibility, again where
gis aGitinstance, could be to allowg.execute.git(*args), accepting zero or more separate positional arguments in place of*argsthat GitPython would immediately rungitwith. I find this intuitive, and it could be achieved by making theexecutemethod a custom descriptor that works like a bound method, except that it also causesg.execute.gitto resolve tog._call_process, andGit.execute.gitto resolve toGit._call_process(so it also works explicitly passgto the unbound form, as methods are expected to support).But the problem with this is that it is not obvious whether the "submethod" ought to continue being usable when a class that derives from
Gitoverridesexecute. Secondarily, I think having overrides turn into descriptors that also support.gitwould be complicated, and might go against assumptions people make about he effect of writing a subclass.To be clear, the problem is not that overriding
executeaffects the behavior. That is already the case with_call_processand everything that uses it, and is probably the main reason for a subclass ofGitto overrideexecute. Rather, the question is whetherMyGit().execute.git(*args)andMyGit().execute.git(my_g, *args)should work and, if so, whether the complexity to make it work is justified.Other ways, which also don't seem ideal
Other possibilities include:
g._(*args). This seems unintuitive.Gitobject is constructed to enable new methods.Gitclass the same but providing a derived class ofGitthat includes new methods.Gitobject as its first argument.Gitobject.gitcommand (but the more reliably they are not, the less intuitive the command is, probably).gitcommand (relative or absolute path) that_call_processpasses toexecute, and noting how to useexecutewith it inexecute's docstring, elsewhere in the documentation, or both.A hack that shouldn't be used
By the way, it turns out there actually is a way I could have used the "public" interface to achieve the effect of
g._call_process("--exec-path"). Becausegitaccepts a--after this option with no change in behavior, we can fool GitPython into thinking--is the subcommand. Where againgis aGitinstance:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's interesting! I wasn't even aware this works. Also I don't know how this interacts with the maybe more typical usage of
repo.git.subcommand(), or is something likerepo.git(c="foo=bar").subcommand()possible?Regarding the multi-issue, maybe it already works like this?
Do you think it's common to subclass
Git? I'd argue that this was never intended and I'd rather forbid it than think about it. And if it can't be prohibited officially, maybe it's possible to document it as "unsupported" which allows subclasses to break if they happen. Of course, that itself would be a breaking change, but I wonder anyone would notice.Also, apologies in advance if what I say here doesn't make much sense or seems to ignore something you already mentioned - I am quite ignorant as to how
Git(the class) is truly working and I really don't know what's best.But simply making
_call_processpublic officially seemed like the easiest while safe-enough way to go to me.PS:
>>> getattr(g(exec_path=True), "--")()is wonderfully creative :D.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does work! This treated both
preandRC1as lower versions than their corresponding stable versions:It does also work with
repo.git(...).subcommand(...):(The repo I tested on doesn't have tags whose order is affected by versionsort, but the debugging output shows that both
-c ...are passed and in the correct positions.)I'm not sure, but it may be possible to effectively search at least code on GitHub and elsewhere where rich code searching is implemented to figure it out. For a lot of stuff using popular projects like GitPython, I find such searching hard, because one gets lots of code in forks and vendored copies of the project. But if GitPython is never itself inheriting from
Gitor testing for that, it may be reasonably easy to find that sort of thing.If I figure anything out about that, I'll let you know. I would intuitively expect to be able to inherit from it.
Yes. If that's acceptable, then I think it should be strongly considered before doing anything more complicated that also expands the GitPython public interface. A further argument for preferring this to other approaches is that it is already referenced in some public methods' docstrings.
:) I guess there's an interesting question about whether the
--"attribute" ofGitinstances should be considered public on the grounds that its name does not start with an underscore. 😺Actually, I had meant to be joking, just then, but it checks out:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am definitely happy to make this a non-feature, or at least document that subclass behaviour might change unannounced.