* Re: [RFC/PATCH 5/6] Let transport_helper_init() decide if a remote helper program can be used
From: Johannes Schindelin @ 2009-08-11 12:21 UTC (permalink / raw)
To: Johan Herland; +Cc: git, barkalow, gitster, benji
In-Reply-To: <1249985426-13726-6-git-send-email-johan@herland.net>
Hi,
On Tue, 11 Aug 2009, Johan Herland wrote:
> diff --git a/transport-helper.c b/transport-helper.c
> index d3ce984..de30727 100644
> --- a/transport-helper.c
> +++ b/transport-helper.c
> @@ -5,6 +5,7 @@
> #include "commit.h"
> #include "diff.h"
> #include "revision.h"
> +#include "help.h"
>
> struct helper_data
> {
> @@ -279,11 +280,18 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
>
> int transport_helper_init(struct transport *transport)
> {
> - struct helper_data *data = xcalloc(sizeof(*data), 1);
> + struct helper_data *data;
> + struct strbuf buf = STRBUF_INIT;
> + char *cmd;
> +
> + if (!transport->remote)
> + return -1;
>
> + data = xcalloc(sizeof(*data), 1);
> if (transport->remote->foreign_vcs) {
> data->name = xstrdup(transport->remote->foreign_vcs);
> - transport->url = transport->remote->foreign_vcs;
> + if (!transport->url)
> + transport->url = transport->remote->foreign_vcs;
> } else {
> char *eom = strchr(transport->url, ':');
> if (!eom) {
IMHO it would be better to decide early if there is no vcs helper, rather
than doing all kinds of set up, only to free() the data we worked so hard
in setting up later. Something like
if (!transport->remote->foreign_vcs) {
const char *colon = transport->url ?
strchr(transport->url, ':') : NULL;
if (!colon)
return -1;
transport->remote->foreign_vcs =
xstrndup(transport->url, colon - transport->url);
}
strbuf_addf(&buf, "remote-%s", transport->remote->foreign_vcs);
if (!is_git_command_or_alias(buf.buf)) {
error("Could not find remote helper '%s'", buf.buf);
strbuf_release(&buf);
return -1;
}
> diff --git a/transport.c b/transport.c
> index 81a28bc..b7033eb 100644
> --- a/transport.c
> +++ b/transport.c
> @@ -794,11 +794,12 @@ struct transport *transport_get(struct remote *remote, const char *url)
> ret->fetch = fetch_objs_via_rsync;
> ret->push = rsync_transport_push;
>
> - } else if (!url
> - || !prefixcmp(url, "http://")
> - || !prefixcmp(url, "https://")
> - || !prefixcmp(url, "ftp://")) {
> - transport_helper_init(ret);
> + } else if ((!url
> + || (prefixcmp(url, "git:")
> + && prefixcmp(url, "ssh:")
> + && prefixcmp(url, "file:")))
> + && !transport_helper_init(ret)) {
> + /* no-op, ret is initialized by transport_helper_init() */
>
> } else if (url && is_local(url) && is_file(url)) {
Confusing...
When is transport_helper_init(ret) called now? What is done in the code
block? Ah, nothing is done, but we usually write that this way:
; /* do nothing */
And a comment would have been in order to say that we fall back to native
Git transport, which will probably silently fail when there is no URL (I
_know_ that allowing two different ways to specify the same thing are not
only inconsistent and confusing, they lead to errors -- if not here then
somewhere else).
Also, you missed two cases mentioned in connect.c: "git+ssh" and
"ssh+git". Which brings me to another thing: I'd rather handle the known
protocols and fall back to a remote helper. The other way round seems
pretty backwards.
Sidenote: I have to admit that I find it distracting that "ret" is passed
to transport_helper_init(), either, it's probably not an "int" but an
instance of struct transport.)
Ciao,
Dscho
^ permalink raw reply
* Re: [RFC/PATCH 4/6] Add is_git_command_or_alias() for checking availability of a given git command
From: Johannes Schindelin @ 2009-08-11 12:21 UTC (permalink / raw)
To: Johan Herland; +Cc: git, barkalow, gitster, benji
In-Reply-To: <1249985426-13726-5-git-send-email-johan@herland.net>
Hi,
On Tue, 11 Aug 2009, Johan Herland wrote:
> diff --git a/help.c b/help.c
> index 994561d..a616277 100644
> --- a/help.c
> +++ b/help.c
> @@ -296,6 +296,27 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
> old->names = NULL;
> }
>
> +int is_git_command_or_alias(const char *cmd)
> +{
> + struct cmdnames main_cmds, other_cmds;
> +
> + memset(&main_cmds, 0, sizeof(main_cmds));
> + memset(&other_cmds, 0, sizeof(other_cmds));
> + memset(&aliases, 0, sizeof(aliases));
> +
> + git_config(git_unknown_cmd_config, NULL);
> +
> + load_command_list("git-", &main_cmds, &other_cmds);
> +
> + add_cmd_list(&main_cmds, &aliases);
> + add_cmd_list(&main_cmds, &other_cmds);
> + qsort(main_cmds.names, main_cmds.cnt,
> + sizeof(main_cmds.names), cmdname_compare);
> + uniq(&main_cmds);
> +
> + return is_in_cmdlist(&main_cmds, cmd);
> +}
Sorting a list is an O(n log n) operation, searching through a list
linearly is O(n). You throw away main_cmds (without freeing) after that,
so I think it is not a good trade-off.
Ciao,
Dscho
^ permalink raw reply
* Re: A tiny documentation patch
From: Michael J Gruber @ 2009-08-11 8:01 UTC (permalink / raw)
To: Thomas Rast; +Cc: Štěpán Němec, git, Junio C Hamano
In-Reply-To: <200908101659.28291.trast@student.ethz.ch>
Thomas Rast venit, vidit, dixit 10.08.2009 16:59:
> Štěpán Němec wrote:
[...]
> [...]
>> -In mirror mode, enabled with `\--mirror`, the refs will not be stored
>> +In mirror mode, enabled with `--mirror`, the refs will not be stored
> [...]
>> -mode, furthermore, `git push` will always behave as if `\--mirror`
>> +mode, furthermore, `git push` will always behave as if `--mirror`
>
> While I'm not sure how far back you'd have to go to find an asciidoc
> that does need this escaping, it's definitely *not* a typo. In some
> instances, -- turns into em dashes.
>
> If you are seeing stray backslashes in the output (I don't), I suspect
> you are either running asciidoc 8.x but forgot to set ASCIIDOC8, or
> 8.4.1+ and are missing the patch 71c020c (Disable asciidoc 8.4.1+
> semantics for `{plus}` and friends, 2009-07-25).
[...]
In current next's Documentation/, we have 149 lines with `-- and 48
lines with `\--. How is our policy regarding old AsciiDoc? I suggest
(read: volunteer) making these things uniform one way or the other,
depending which versions we want to support.
Michael
^ permalink raw reply
* Re: [RFC/PATCH 3/6] Move setup of curl remote helper from transport.c to transport-helper.c
From: Johannes Schindelin @ 2009-08-11 12:23 UTC (permalink / raw)
To: Johan Herland; +Cc: git, barkalow, gitster, benji
In-Reply-To: <1249985426-13726-4-git-send-email-johan@herland.net>
Hi,
On Tue, 11 Aug 2009, Johan Herland wrote:
> diff --git a/transport-helper.c b/transport-helper.c
> index a901630..d3ce984 100644
> --- a/transport-helper.c
> +++ b/transport-helper.c
> @@ -249,6 +249,34 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
> return ret;
> }
>
> +#ifndef NO_CURL
> +static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
> +{
> + const char **argv;
> + int argc;
> +
> + if (flags & TRANSPORT_PUSH_MIRROR)
> + return error("http transport does not support mirror mode");
> +
> + argv = xmalloc((refspec_nr + 12) * sizeof(char *));
> + argv[0] = "http-push";
> + argc = 1;
> + if (flags & TRANSPORT_PUSH_ALL)
> + argv[argc++] = "--all";
> + if (flags & TRANSPORT_PUSH_FORCE)
> + argv[argc++] = "--force";
> + if (flags & TRANSPORT_PUSH_DRY_RUN)
> + argv[argc++] = "--dry-run";
> + if (flags & TRANSPORT_PUSH_VERBOSE)
> + argv[argc++] = "--verbose";
> + argv[argc++] = transport->url;
> + while (refspec_nr--)
> + argv[argc++] = *refspec++;
> + argv[argc] = NULL;
> + return !!run_command_v_opt(argv, RUN_GIT_CMD);
> +}
> +#endif
> +
> int transport_helper_init(struct transport *transport)
> {
> struct helper_data *data = xcalloc(sizeof(*data), 1);
> @@ -269,5 +297,16 @@ int transport_helper_init(struct transport *transport)
> transport->get_refs_list = get_refs_list;
> transport->fetch = fetch;
> transport->disconnect = disconnect_helper;
> +
> + if (!strcmp(data->name, "http")
> + || !strcmp(data->name, "https")
> + || !strcmp(data->name, "ftp")) {
> +#ifdef NO_CURL
> + error("git was compiled without libcurl support.");
> +#else
> + transport->push = curl_transport_push;
> +#endif
> + }
> +
> return 0;
> }
I still find it rather, uhm, confusing that copying git-http-push and/or
git-remote-http into place will still give you the error message "Git was
compiled without libcurl support".
It's just as well that I do not need to maintain RPMs or DEBs.
Ciao,
Dscho
^ permalink raw reply
* Re: Unable to checkout a branch after cloning
From: Matthew Lear @ 2009-08-11 12:17 UTC (permalink / raw)
To: Michael J Gruber; +Cc: git
In-Reply-To: <4A815E49.60406@drmicha.warpmail.net>
Hi Michael - thanks for your reply.
Michael J Gruber wrote:
> Matthew Lear venit, vidit, dixit 11.08.2009 12:10:
>> Hi all,
>>
>> Apologies for perhaps a silly question, but I'd very much appreciate a
>> little bit of assistance.
>>
>> I've set up a git repository on a machine accessible from the internet
>> with the intention to share code with another developer. We clone the
>> repository, commit changes then push back as you'd expect. The server
>> runs gitweb for repository browsing. Clients are running git v1.6.0.6.
>>
>> When I created the initial repository I also created two additional
>> branches - 'upstream' and 'custom'. The former is to act as a 'vendor
>> branch' and the latter contains code specific to the custom platform
>> that we're working on. The master branch contains merges from the
>> upstream branch and also changes that we've made. The custom branch
>> contains merges from master with custom platform specific changes.
>>
>> I've committed changes and on both upstream and custom branches as work
>> progressed, merged them where appropriate, added tags etc and pushed
>> everything to the remote repository. No problem. I can view the
>> branches, tags etc in gitweb and everything looks fine.
>>
>> However, I can clone a new repository just fine but I'm unable to
>> checkout the upstream or custom branches. After cloning, only the master
>> branch is available, ie:
>>
>>> git checkout upstream
>> error: pathspec 'upstream' did not match any file(s) known to git.
>>
>>> git branch -a
>> * master
>> origin/HEAD
>> origin/master
>>
>> .git/config:
>>
>> [core]
>> repositoryformatversion = 0
>> filemode = true
>> bare = false
>> logallrefupdates = true
>> [remote "origin"]
>> url = https://mysite/git/project.git
>> fetch = +refs/heads/*:refs/remotes/origin/*
>> [branch "master"]
>> remote = origin
>> merge = refs/heads/master
>>
>> But the initial local repository where I work (ie created the branches,
>> committed changes, tag, push etc) seems to be fine, ie
>>
>>> git checkout upstream
>> Switched to branch "upstream"
>>
>>> git branch -a
>> custom
>> * master
>> upstream
>>
>> .git/config:
>>
>> [core]
>> repositoryformatversion = 0
>> filemode = true
>> bare = false
>> logallrefupdates = true
>> [remote "origin"]
>> url = https://mysite/git/project.git
>> fetch = +refs/heads/*:refs/remotes/origin/*
>>
>>
>> Developers need to be able to clone the repository and then switch to
>> the appropriate branch in order to work. However it seems that after a
>> clone, only the master branch is available.
>>
>> Why is this?
>>
>> Any help would be much appreciated indeed.
>
> If I understand you correctly you have 3 repos: the "initial" one on
> which everything is as expected, the "server" one and the "new clone"
> which is missing branches.
Yes, that's correct.
> Now: How's the server one doing, i.e. what does "git ls-remote
> https://mysite/git/project.git" say? I suspect that one either does not
> have the branches (you haven't told us how you pushed) or in the wrong
> place (remotes/).
> git ls-remote https://mysite/git/project.git
065f5f13d5f8e786729db1623cc53767c963e959 HEAD
065f5f13d5f8e786729db1623cc53767c963e959 refs/heads/master
Hmm. So it seems that the branches are not actually on the server
repository. So how come I can see them with gitweb..?
I've been pushing from the 'initial' repository with git push --all and
git push --tags.
However, when I try a git push from the initial repository I get the
following:
> git push --all
Fetching remote heads...
refs/
refs/heads/
refs/tags/
'refs/heads/custom': up-to-date
'refs/heads/master': up-to-date
'refs/heads/upstream': up-to-date
-- Matt
^ permalink raw reply
* Re: [RFC PATCH v2 3/4] unpack_trees(): add support for sparse checkout
From: Johannes Schindelin @ 2009-08-11 7:02 UTC (permalink / raw)
To: Nguyen Thai Ngoc Duy; +Cc: git
In-Reply-To: <fcaeb9bf0908101847w7b3b22d9w84514a29ceae719e@mail.gmail.com>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 2650 bytes --]
Hi,
On Tue, 11 Aug 2009, Nguyen Thai Ngoc Duy wrote:
> 2009/8/10 Johannes Schindelin <Johannes.Schindelin@gmx.de>:
>
> > On Mon, 10 Aug 2009, Nguyễn Thái Ngọc Duy wrote:
> >
> >> This patch teaches unpack_trees() to checkout/remove entries on
> >> working directories appropriately when sparse checkout area is
> >> changed. Hook "sparse" is needed to help determine which entry will
> >> be checked out, which will not be.
> >>
> >> When the hook is run, it is prepared with a pseudo index. The hook
> >> then can use "git update-index --[no-]assume-unchanged" to manipulate
> >> the index. It should not do anything else on the index. Assume
> >> unchanged information from the index will be used to shape working
> >> directory.
> >
> > If I understand correctly, the purpose of the hook is to allow the
> > user to mark something as unwanted preemptively, right?
> >
> > If that is the sole reason for the hook, would it not be better to add
> > support for a file .git/info/sparse which has the same syntax as
> > .git/info/exclude, and which is used to determine if an
> > added/modified/deleted file is supposed to be in the "sparse" area or
> > not?
> >
> > Something like
> >
> > *
> > !/Documentation/
> >
> > comes to mind.
>
> That was what the original series was about (although I used git
> config instead of .git/info/sparse). The hook has two advantages:
>
> - flexibility: you can set things differently based on branch, for
> example, or filter files based on certain file content.
True, it is flexible. The question is: is it not too flexible for its own
good?
Having to introduce a hook means that every user either must trust another
person and install the unmodified hook, or write the hook herself for
every narrow work tree.
The branch use case you mentioned is maybe a good example what I mean by
"too flexible":
- it is easy to get confused which parts are narrow or not if the hook can
change that depending on, say, the phase of the moon (okay, okay,
depending on the branch, but it is still confusing),
- the whole purpose of narrow checkout is to avoid having to check out
stuff that does not affect you. Chances are that 99.99% of all "narrow"
users do not need to modify which slice of the files they want to see,
and those who do are probably better off with two work trees, methinks.
> - less code bloat (and less intrusive too), compare ~1000 lines of
> change of the original series with this series.
Heh, see my other mail. I'm sorry I forgot to mention that the similarity
to .gitignore spares you a lot of code...
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH 4/6 (v2)] administrative functions for rev-cache, and start of integration into git
From: Nick Edelen @ 2009-08-11 9:49 UTC (permalink / raw)
To: Junio C Hamano
Cc: Nicolas Pitre, Johannes Schindelin, Sam Vilain, Michael J Gruber,
Jeff King, Shawn O. Pearce, Andreas Ericsson, Christian Couder,
git@vger.kernel.org
In-Reply-To: <7vtz0g7s1p.fsf@alter.siamese.dyndns.org>
> It is unclear which "size" this field refers to without comment.
>
> I do not know if this change is justifiable. We (mostly Linus) spent
> considerble effort to shrink the memory footprint of struct commit (and
> struct object in general) exactly because revision traversal needs to
> inspect tons of them.
I originally added a `size` field to objects, a `unique` field to
commits and `name` ones to blobs/trees. This was (I reasoned) partly
for applications to take fuller advantage of rev-cache's abilities,
but largely to ease re-use of its information in slice regeneration.
However, in retrospect I think you're probably right. Not only do I
not really need to load the information into memory to re-use it, but
applications using rev-cache would probably have sufficiently
specialized needs to warrant direct access. In light of this I've
rewritten the fuse command to re-use data directly from the slice,
rather than requiring it to be loaded into memory first (hence
eliminating the all those extra fields). Furthermore I'll put all the
(renamed) structures and definitions in a seperate header, to allow
easy direct access to slices by third-parties.
> Looks vaguely familiar.
>
> The configuration parser already knows about these size suffixes when told
> to read "int". Can't that code, e.g. git_parse_ulong(), be reused here?
You're also right here. I wrote it fast and hadn't checked if git had
already implemented it. I've changed it to use git_parse_ulong().
Sorry I haven't uploaded anything yet. I keep seeing new things that
could updated or revised; so far I've
- rewritten and added much to the documentation
- added support for an alternates-like mechanism
- changed --noobjects to --no-objects
- changed init_rci to init_rev_cache_info
- modified make_cache_slice to return actual start/end commits
- changed coagulate_ to fuse_
- added an (admittedly crude) escape plan in case of obscenely large
merges/branches
- cleaned up path generation
- replace parse_size with git_parse_ulong
- rewritten fuse to reuse objects verbatim, rather than via memory access
And on my todo list I've still got things such as renaming all the
structures/definitions, adding a more portable _ondisk version of
bitfield'ed structs and obviously cleanup the patchset (eliminating
fixes of earlier patches, etc.).
I hope to get everything finished in the next couple days, and upload
a v3 by friday at the latest.
- Nick
^ permalink raw reply
* Re: bug with .git file and aliases
From: Johannes Schindelin @ 2009-08-11 8:33 UTC (permalink / raw)
To: Geoffrey Irving; +Cc: Jeff King, git, Lars Hjemli
In-Reply-To: <7f9d599f0908102037s51f0380te56463706f794c8a@mail.gmail.com>
Hi,
On Mon, 10 Aug 2009, Geoffrey Irving wrote:
> On Mon, Aug 10, 2009 at 7:05 PM, Johannes
> Schindelin<Johannes.Schindelin@gmx.de> wrote:
>
> > The proper fix, of course, is to avoid calling the function with the
> > wrong path to begin with.
>
> I'm happy that the correct fix is obvious, and apologize for missing it.
No, no, I said that it is obvious what should be fixed (you do not want
to break perfectly valid workflows such as having a worktree set in the
config, but overriding it via git's --work-tree option). The fix is not
obvious, unfortunately.
See also http://thread.gmane.org/gmane.comp.version-control.git/102269 for
some discussion on the same topic.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH 5/8] Add a config option for remotes to specify a foreign vcs
From: Johannes Schindelin @ 2009-08-11 8:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johan Herland, git, Daniel Barkalow, Brian Gernhardt
In-Reply-To: <7vmy67orwr.fsf@alter.siamese.dyndns.org>
Hi,
On Mon, 10 Aug 2009, Junio C Hamano wrote:
> Johan Herland <johan@herland.net> writes:
>
> > I'm somewhat agnostic on this issue. At the moment, I follow the P4
> > cues, and use a config like this:
> >
> > [remote "foo"]
> > vcs = cvs
> > cvsRoot = ":pserver:user@cvs.server.example.com/var/cvs/cvsroot"
> > cvsModule = "bar"
> > ...
> >
> > But I could just as well use a config like this instead:
> >
> > [remote "foo"]
> > url = "cvs::pserver:user@cvs.server.example.com/var/cvs/cvsroot#bar"
> > ...
> >
> > Either is fine with me, although I suspect users might find the
> > current/first alternative easier to parse.
>
> Ah, ok, that is a much better (rather, easier to understand for _me_)
> example to illustrate what Daniel meant, and I can well imagine P4
> counterpart of cvsRoot may resemble an URL even less than your cvsRoot
> example does.
>
> If the foreign system uses a single string as "the string to identify
> location", like the latter (which is a good example, even though I do not
> think a CVS folks write a reference to a module like you wrote), then I
> think it makes sense to use that form as remote.$name.url. But if naming
> a location with a single simple string is an alien notion to the foreign
> system, I agree with Daniel that we do not gain much by trying to shoehorn
> them into a single remote.$name.url configuration.
Of course, it is always nice to be able to tell people: just clone the
repository with
git clone cvs::pserver:anonymous@cool.haxx.se:/cvsroot/curl#curl
Rather than telling them: "you know, it is really trivial once you
understand the inner workings of Git. Just follow this recipe for the
moment, and you are all set up:
1) mkdir curl
2) cd curl
3) git init
4) git remote.origin.vcs cvs
5) git remote.origin.cvsRoot :pserver:anonymous@cool.haxx.se:/cvsroot/curl
6) git remote.origin.cvsModule curl
7) git fetch origin
8) git checkout --track origin/master
Oh, and please ignore that warning in the last step telling you that you
are already on branch 'master', that is perfectly normal."
I don't know, but this sounds more and more like the complicator's glove
to me (with the same reactions).
Ciao,
Dscho
^ permalink raw reply
* Re: [EGIT] Push to GitHub caused corruption
From: Robin Rosenberg @ 2009-08-11 6:10 UTC (permalink / raw)
To: John Bito; +Cc: git
In-Reply-To: <3ae83b000908101446q2d4f1101we4bbd7023f78b03@mail.gmail.com>
måndag 10 augusti 2009 23:46:34 skrev John Bito <jwbito@gmail.com>:
> Using the 'release' build of EGit (0.4.9.200906240051) I pushed a
> commit to GitHub. After that, using git to pull, I get 'bad tree
> object' resulting in 'remote: aborting due to possible repository
> corruption on the remote side'. I had a similar problem back in April
> (using integration builds of 0.4.0). I'm willing to investigate if
> there's interest in finding the root of the problem.
Fixing problems related to repository integrity is definitely interesting. One
can live all kinds of problem, as long as they don't destroy anything.
-- robin
^ permalink raw reply
* Re: git gc expanding packed data?
From: Hin-Tak Leung @ 2009-08-11 10:17 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: git
In-Reply-To: <alpine.LFD.2.00.0908042203380.16073@xanadu.home>
On Wed, Aug 5, 2009 at 11:39 PM, Nicolas Pitre<nico@cam.org> wrote:
> On Tue, 4 Aug 2009, Hin-Tak Leung wrote:
>
>> I cloned gcc's git about a week ago to work on some problems I have
>> with gcc on minor platforms, just plain 'git clone
>> git://gcc.gnu.org/git/gcc.git gcc' .and ran gcc fetch about daily, and
>> 'git rebase origin' from time to time. I don't have local changes,
>> just following and monitoring what's going on in gcc. So after a week,
>> I thought I'd do a git gc . Then it goes very bizarre.
>>
>> Before I start 'git gc', .The whole of .git was about 700MB and
>> git/objects/pack was a bit under 600MB, with a few other directories
>> under .git/objects at 10's of K's and a few 30000-40000K's, and the
>> checkout was, well, the size of gcc source code. But after I started
>> git gc, the message stays in the 'counting objects' at about 900,000
>> for a long time, while a lot of directories under .git/objects/ gets a
>> bit large, and .git blows up to at least 7GB with a lot of small files
>> under .git/objects/*/, before seeing as I will run out of disk space,
>> I kill the whole lot and ran git clone again, since I don't have any
>> local change and there is nothing to lose.
>>
>> I am running git version 1.6.2.5 (fedora 11). Is there any reason why
>> 'git gc' does that?
>
> There is probably a reason, although a bad one for sure.
>
> Well... OK.
>
> It appears that the git installation serving clone requests for
> git://gcc.gnu.org/git/gcc.git generates lots of unreferenced objects. I
> just cloned it and the pack I was sent contains 1383356 objects (can be
> determined with 'git show-index < .git/objects/pack/*.idx | wc -l').
> However, there are only 978501 actually referenced objects in that
> cloned repository ( 'git rev-list --all --objects | wc -l'). That makes
> for 404855 useless objects in the cloned repository.
>
> Now git has a safety mechanism to _not_ delete unreferenced objects
> right away when running 'git gc'. By default unreferenced objects are
> kept around for a period of 2 weeks. This is to make it easy for you to
> recover accidentally deleted branches or commits, or to avoid a race
> where a just-created object in the process of being but not yet
> referenced could be deleted by a 'git gc' process running in parallel.
>
> So to give that grace period to packed but unreferenced objects, the
> repack process pushes those unreferenced objects out of the pack into
> their loose form so they can be aged and eventually pruned. Objects
> becoming unreferenced are usually not that many though. Having 404855
> unreferenced objects is quite a lot, and being sent those objects in the
> first place via a clone is stupid and a complete waste of network
> bandwidth.
>
> Anyone has an idea of the git version running on gcc.gnu.org? It is
> certainly buggy and needs fixing.
>
> Anyway... To solve your problem, you simply need to run 'git gc' with
> the --prune=now argument to disable that grace period and get rid of
> those unreferenced objects right away (safe only if no other git
> activities are taking place at the same time which should be easy to
> ensure on a workstation). The resulting .git/objects directory size
> will shrink to about 441 MB. If the gcc.gnu.org git server was doing
> its job properly, the size of the clone transfer would also be
> significantly smaller, meaning around 414 MB instead of the current 600+
> MB.
>
> And BTW, using 'git gc --aggressive' with a later git version (or
> 'git repack -a -f -d --window=250 --depth=250') gives me a .git/objects
> directory size of 310 MB, meaning that the actual repository with all
> the trunk history is _smaller_ than the actual source checkout. If that
> repository was properly repacked on the server, the clone data transfer
> would be 283 MB. This is less than half the current clone transfer
> size.
>
>
> Nicolas
>
'git gc --prune=now' does work, but 'git gc --prune=now --aggressive'
(before) and 'git gc --aggressive' (after) both create very large
(>2GB; I stopped it) packs from the ~400MB-600MB packed objects. I
noted that you specifically wrote 'with a later git version' -
presumably there is a some sort of a known and fixed issue there? Just
curious.
I guess --aggressive doesn't always save space...
Hin-Tak
^ permalink raw reply
* Re: [PATCH v2] push: point to 'git pull' and 'git push --force' in case of non-fast forward
From: Nanako Shiraishi @ 2009-08-11 3:03 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Matthieu Moy, Teemu Likonen, git
In-Reply-To: <7vy6pujmsc.fsf@alter.siamese.dyndns.org>
From: Matthieu Moy <Matthieu.Moy@imag.fr>
Date: Sat, 8 Aug 2009 09:51:08 +0200
Subject: [PATCH] push: point to 'git pull' and 'git push --force' in case of non-fast forward
'git push' failing because of non-fast forward is a very common situation,
and a beginner does not necessarily understand "fast forward" immediately.
Add a new section to the git-push documentation and refer them to it.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Nanako Shiraishi <nanako3@lavabit.com>
---
Quoting Junio C Hamano <gitster@pobox.com> writes:
> So how about phrasing it like this?
>
> Non-fast forward pushes were rejected because you would discard remote
> changes you have not seen. Integrate them with your changes and then
> push again. See 'non-fast forward' section of 'git push --help'.
>
> I think you can throw in a discussion on --force to the manual page, too.
Here is my attempt to coagulate the improvements discussed on the thread so far. I added a paragraph that mentions --force in the new section of the manual, reworded the explanatory message on the UI, and forged two signatures.
Documentation/git-push.txt | 86 ++++++++++++++++++++++++++++++++++++++++++++
builtin-push.c | 9 ++++-
transport.c | 10 ++++--
transport.h | 3 +-
4 files changed, 103 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 2653388..58d2bd5 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -195,6 +195,92 @@ reason::
refs, no explanation is needed. For a failed ref, the reason for
failure is described.
+Note about fast-forwards
+------------------------
+
+When an update changes a branch (or more in general, a ref) that used to
+point at commit A to point at another commit B, it is called a
+fast-forward update if and only if B is a descendant of A.
+
+In a fast-forward update from A to B, the set of commits that the original
+commit A built on top of is a subset of the commits the new commit B
+builds on top of. Hence, it does not lose any history.
+
+In contrast, a non-fast-forward update will lose history. For example,
+suppose you and somebody else started at the same commit X, and you built
+a history leading to commit B while the other person built a history
+leading to commit A. The history looks like this:
+
+----------------
+
+ B
+ /
+ ---X---A
+
+----------------
+
+Further suppose that the other person already pushed changes leading to A
+back to the original repository you two obtained the original commit X.
+
+The push done by the other person updated the branch that used to point at
+commit X to point at commit A. It is a fast-forward.
+
+But if you try to push, you will attempt to update the branch (that
+now points at A) with commit B. This does _not_ fast-forward. If you did
+so, the changes introduced by commit A will be lost, because everybody
+will now start building on top of B.
+
+The command by default does not allow an update that is not a fast-forward
+to prevent such loss of history.
+
+If you do not want to lose your work (history from X to B) nor the work by
+the other person (history from X to A), you would need to first fetch the
+history from the repository, create a history that contains changes done
+by both parties, and push the result back.
+
+You can perform "git pull", resolve potential conflicts, and "git push"
+the result. A "git pull" will create a merge commit C between commits A
+and B.
+
+----------------
+
+ B---C
+ / /
+ ---X---A
+
+----------------
+
+Updating A with the resulting merge commit will fast-forward and your
+push will be accepted.
+
+Alternatively, you can rebase your change between X and B on top of A,
+with "git pull --rebase", and push the result back. The rebase will
+create a new commit D that builds the change between X and B on top of
+A.
+
+----------------
+
+ B D
+ / /
+ ---X---A
+
+----------------
+
+Again, updating A with this commit will fast-forward and your push will be
+accepted.
+
+There is another common situation where you may encounter non-fast-forward
+rejection when you try to push, and it is possible even when you are
+pushing into a repository nobody else pushes into. After you push commit
+A yourself (in the first picture in this section), replace it with "git
+commit --amend" to produce commit B, and you try to push it out, because
+forgot that you have pushed A out already. In such a case, and only if
+you are certain that nobody in the meantime fetched your earlier commit A
+(and started building on top of it), you can run "git push --force" to
+overwrite it. In other words, "git push --force" is a method reserved for
+a case where you do mean to lose history.
+
+
Examples
--------
diff --git a/builtin-push.c b/builtin-push.c
index 1d92e22..50328f4 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -140,6 +140,7 @@ static int do_push(const char *repo, int flags)
struct transport *transport =
transport_get(remote, url[i]);
int err;
+ int nonfastforward;
if (receivepack)
transport_set_option(transport,
TRANS_OPT_RECEIVEPACK, receivepack);
@@ -148,13 +149,19 @@ static int do_push(const char *repo, int flags)
if (flags & TRANSPORT_PUSH_VERBOSE)
fprintf(stderr, "Pushing to %s\n", url[i]);
- err = transport_push(transport, refspec_nr, refspec, flags);
+ err = transport_push(transport, refspec_nr, refspec, flags,
+ &nonfastforward);
err |= transport_disconnect(transport);
if (!err)
continue;
error("failed to push some refs to '%s'", url[i]);
+ if (nonfastforward) {
+ printf("To prevent you from losing history, non-fast-forward updates were rejected.\n"
+ "Merge the remote changes before pushing again.\n"
+ "See 'non-fast forward' section of 'git push --help' for details.\n");
+ }
errs++;
}
return !!errs;
diff --git a/transport.c b/transport.c
index de0d587..f231b35 100644
--- a/transport.c
+++ b/transport.c
@@ -820,7 +820,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
}
static void print_push_status(const char *dest, struct ref *refs,
- int verbose, int porcelain)
+ int verbose, int porcelain, int * nonfastforward)
{
struct ref *ref;
int n = 0;
@@ -835,11 +835,14 @@ static void print_push_status(const char *dest, struct ref *refs,
if (ref->status == REF_STATUS_OK)
n += print_one_push_status(ref, dest, n, porcelain);
+ *nonfastforward = 0;
for (ref = refs; ref; ref = ref->next) {
if (ref->status != REF_STATUS_NONE &&
ref->status != REF_STATUS_UPTODATE &&
ref->status != REF_STATUS_OK)
n += print_one_push_status(ref, dest, n, porcelain);
+ if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD)
+ *nonfastforward = 1;
}
}
@@ -997,7 +1000,8 @@ int transport_set_option(struct transport *transport,
}
int transport_push(struct transport *transport,
- int refspec_nr, const char **refspec, int flags)
+ int refspec_nr, const char **refspec, int flags,
+ int * nonfastforward)
{
verify_remote_names(refspec_nr, refspec);
@@ -1024,7 +1028,7 @@ int transport_push(struct transport *transport,
ret = transport->push_refs(transport, remote_refs, flags);
- print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);
+ print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain, nonfastforward);
if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
struct ref *ref;
diff --git a/transport.h b/transport.h
index 51b5397..639f13d 100644
--- a/transport.h
+++ b/transport.h
@@ -68,7 +68,8 @@ int transport_set_option(struct transport *transport, const char *name,
const char *value);
int transport_push(struct transport *connection,
- int refspec_nr, const char **refspec, int flags);
+ int refspec_nr, const char **refspec, int flags,
+ int * nonfastforward);
const struct ref *transport_get_remote_refs(struct transport *transport);
--
1.6.2.GIT
--
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
^ permalink raw reply related
* Re: bug with .git file and aliases
From: Michael J Gruber @ 2009-08-11 10:04 UTC (permalink / raw)
To: Jeff King
Cc: Geoffrey Irving, git, Lars Hjemli, Johannes Sixt,
Johannes Schindelin
In-Reply-To: <20090720152117.GB5347@coredump.intra.peff.net>
Jeff King venit, vidit, dixit 20.07.2009 17:21:
> On Mon, Jul 20, 2009 at 09:54:12AM -0400, Geoffrey Irving wrote:
>
>> git 1.6.3.3 has a bug related to .git file support and aliases.
>> Specifically, if you make an alias for status and call it from a
>> subdirectory, git status chdirs into the true .git dir but then
>> chdir's back to the wrong place in order to run the lstats for status.
>> The result is that git status thinks all files have disappeared.
>
> Yeah, this is a known problem. The problem is that the 'git' wrapper
> sets up the environment only partially when running aliases, and then
> the resulting command ends up confused about where the worktree is. I
> really don't remember the specifics, but you can probably find some
> discussion in the list archives. Fixing it, IIRC, required some
> refactoring of the setup code (which I had hoped to get to at some
> point, but I am way behind on my git todo list).
>
> Hmm. Poking around a bit, this seems related, but I don't know why I
> never followed up:
>
> http://article.gmane.org/gmane.comp.version-control.git/72792
>
> -Peff
...because it was up to the brave git-on-win folks to decide whether
setenv() on win would be rewritten to not use putenv() when the value is
"". J&J, has anything happened on the front or is it likely to? (I'm
sorry I can't offer help, only moral support...)
Jeff's patch from Feb. 08 still applies more or less cleanly (with
obvious adjustments) and makes the relevant tests pass (on Linux).
Michael
^ permalink raw reply
* Re: [Feature Request] git export
From: Michael J Gruber @ 2009-08-11 7:50 UTC (permalink / raw)
To: thomas; +Cc: git
In-Reply-To: <200908101822.59940.thomas@koch.ro>
Thomas Koch venit, vidit, dixit 10.08.2009 18:22:
> could you please provide a simple solution to save a tree object into an
> arbitrary location?
> I found some hints, that it would be possible by missusing either git
> checkout-index or git-archive, but I think that it shouldn't require that much
> GIT FU to do such a simple thing.
>
> Thanks,
>
> Thomas Koch, http://www.koch.ro
To serve you with an explicit command line, it's really only
git archive HEAD | tar -C wheretoexport/ -xf-
which you need to issue from within your git repo. Instead of HEAD, you
can use any "treeish", for example the name of a branch, which need not
be checked out. You can add path arguments after the treeish if you want
to export only parts of your repo.
Note that in true unix philosophy, git archive does the (git specific)
exporting only and leaves the importing into the file system (saving) to
the proper tool. I mean, would you rather use cp -r or pipes with tar
-x/tar -c or cpio -i/-o in order to copy a tree? ;)
Cheers,
Michael
^ permalink raw reply
* Re: bug with .git file and aliases
From: Johannes Sixt @ 2009-08-11 10:26 UTC (permalink / raw)
To: Michael J Gruber
Cc: Jeff King, Geoffrey Irving, git, Lars Hjemli, Johannes Schindelin
In-Reply-To: <4A814216.20708@drmicha.warpmail.net>
Michael J Gruber schrieb:
> ...because it was up to the brave git-on-win folks to decide whether
> setenv() on win would be rewritten to not use putenv() when the value is
> "". J&J, has anything happened on the front or is it likely to? (I'm
> sorry I can't offer help, only moral support...)
Nothing has changed since. Nothing is likely to happen until there is a
need to touch compat/setenv.c, like, for example, a test in the test suite
that fails only on Windows...
-- Hannes
^ permalink raw reply
* [PATCH] Change mentions of "git programs" to "git commands"
From: Nanako Shiraishi @ 2009-08-11 3:58 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Ori Avtalion
In-Reply-To: <4a7c3971.170d660a.3caa.20b3@mx.google.com>
From: Ori Avtalion <ori@avtalion.name>
Date: Fri, 7 Aug 2009 17:24:21 +0300
Subject: [PATCH] Change mentions of "git programs" to "git commands"
Most of the docs and printouts refer to "commands" when discussing what
the end users call via the "git" top-level program. We should refer them
as "git programs" when we discuss the fact that the commands are
implemented as separate programs, but in other contexts, it is better to
use the term "git commands" consistently.
Signed-off-by: Ori Avtalion <ori@avtalion.name>
Signed-off-by: Nanako Shiraishi <nanako3@lavabit.com>
---
Junio, it appeard to me that you had some minor issues with Ori's patch but you knew exactly how they should be addressed and you thought it was a good change overall.
I copy-edited Ori's patch for your convenience, and tried to clarify the criteria you used to decide which "program" should become "command" in the updated commit log message, in case you forgot to apply it yourself.
I just didn't want to see the time you and others spent on submitting and reviewing wasted due to lack of resubmission of a revised patch.
Documentation/config.txt | 4 ++--
Documentation/fetch-options.txt | 2 +-
Documentation/git-rev-list.txt | 2 +-
Documentation/git.txt | 4 ++--
Documentation/gitattributes.txt | 2 +-
Documentation/gitcore-tutorial.txt | 4 ++--
Documentation/user-manual.txt | 2 +-
help.c | 2 +-
8 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index c6f09f8..e94a8ab 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -605,7 +605,7 @@ color.interactive.<slot>::
Use customized color for 'git-add --interactive'
output. `<slot>` may be `prompt`, `header`, `help` or `error`, for
four distinct types of normal output from interactive
- programs. The values of these variables may be specified as
+ commands. The values of these variables may be specified as
in color.branch.<slot>.
color.pager::
@@ -1113,7 +1113,7 @@ instaweb.port::
linkgit:git-instaweb[1].
interactive.singlekey::
- In interactive programs, allow the user to provide one-letter
+ In interactive commands, allow the user to provide one-letter
input with a single key (i.e., without hitting enter).
Currently this is used only by the `\--patch` mode of
linkgit:git-add[1]. Note that this setting is silently
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index d313795..20bf512 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -1,7 +1,7 @@
-q::
--quiet::
Pass --quiet to git-fetch-pack and silence any other internally
- used programs.
+ used git commands.
-v::
--verbose::
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index bf98c84..21ccccd 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -90,7 +90,7 @@ between the two operands. The following two commands are equivalent:
$ git rev-list A...B
-----------------------------------------------------------------------
-'git-rev-list' is a very essential git program, since it
+'rev-list' is a very essential git command, since it
provides the ability to build and traverse commit ancestry graphs. For
this reason, it has a lot of different options that enables it to be
used by commands as different as 'git-bisect' and
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 5fd5953..fe13e09 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -327,7 +327,7 @@ Synching repositories
include::cmds-synchingrepositories.txt[]
-The following are helper programs used by the above; end users
+The following are helper commands used by the above; end users
typically do not use them directly.
include::cmds-synchelpers.txt[]
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index aaa073e..1195e83 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -404,7 +404,7 @@ Performing a three-way merge
The attribute `merge` affects how three versions of a file is
merged when a file-level merge is necessary during `git merge`,
-and other programs such as `git revert` and `git cherry-pick`.
+and other commands such as `git revert` and `git cherry-pick`.
Set::
diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt
index 7ba5e58..b3640c4 100644
--- a/Documentation/gitcore-tutorial.txt
+++ b/Documentation/gitcore-tutorial.txt
@@ -12,7 +12,7 @@ git *
DESCRIPTION
-----------
-This tutorial explains how to use the "core" git programs to set up and
+This tutorial explains how to use the "core" git commands to set up and
work with a git repository.
If you just need to use git as a revision control system you may prefer
@@ -1328,7 +1328,7 @@ into it later. Obviously, this repository creation needs to be
done only once.
[NOTE]
-'git-push' uses a pair of programs,
+'git-push' uses a pair of commands,
'git-send-pack' on your local machine, and 'git-receive-pack'
on the remote machine. The communication between the two over
the network internally uses an SSH connection.
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index 0b88a51..67ebffa 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -4131,7 +4131,7 @@ What does this mean?
`git rev-list` is the original version of the revision walker, which
_always_ printed a list of revisions to stdout. It is still functional,
-and needs to, since most new Git programs start out as scripts using
+and needs to, since most new Git commands start out as scripts using
`git rev-list`.
`git rev-parse` is not as important any more; it was only used to filter out
diff --git a/help.c b/help.c
index 6c46d8b..57a0e0e 100644
--- a/help.c
+++ b/help.c
@@ -334,7 +334,7 @@ const char *help_unknown_cmd(const char *cmd)
const char *assumed = main_cmds.names[0]->name;
main_cmds.names[0] = NULL;
clean_cmdnames(&main_cmds);
- fprintf(stderr, "WARNING: You called a Git program named '%s', "
+ fprintf(stderr, "WARNING: You called a Git command named '%s', "
"which does not exist.\n"
"Continuing under the assumption that you meant '%s'\n",
cmd, assumed);
--
1.6.2.GIT
--
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
^ permalink raw reply related
* [RFC/PATCH 1/6] Minor unrelated fixes
From: Johan Herland @ 2009-08-11 10:10 UTC (permalink / raw)
To: git; +Cc: Johan Herland, barkalow, gitster, benji, Johannes.Schindelin
In-Reply-To: <alpine.LNX.2.00.0908101205120.27553@iabervon.org>
Signed-off-by: Johan Herland <johan@herland.net>
---
help.c | 2 +-
transport-helper.c | 6 ++++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/help.c b/help.c
index 6c46d8b..994561d 100644
--- a/help.c
+++ b/help.c
@@ -302,7 +302,7 @@ const char *help_unknown_cmd(const char *cmd)
struct cmdnames main_cmds, other_cmds;
memset(&main_cmds, 0, sizeof(main_cmds));
- memset(&other_cmds, 0, sizeof(main_cmds));
+ memset(&other_cmds, 0, sizeof(other_cmds));
memset(&aliases, 0, sizeof(aliases));
git_config(git_unknown_cmd_config, NULL);
diff --git a/transport-helper.c b/transport-helper.c
index cc99368..a901630 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -8,7 +8,7 @@
struct helper_data
{
- const char *name;
+ char *name;
struct child_process *helper;
char *marks_filename;
@@ -258,8 +258,10 @@ int transport_helper_init(struct transport *transport)
transport->url = transport->remote->foreign_vcs;
} else {
char *eom = strchr(transport->url, ':');
- if (!eom)
+ if (!eom) {
+ free(data);
return -1;
+ }
data->name = xstrndup(transport->url, eom - transport->url);
}
--
1.6.4.rc3.138.ga6b98.dirty
^ permalink raw reply related
* [RFC/PATCH 0/6] Graceful handling of missing remote helpers
From: Johan Herland @ 2009-08-11 10:10 UTC (permalink / raw)
To: git; +Cc: Johan Herland, barkalow, gitster, benji, Johannes.Schindelin
In-Reply-To: <alpine.LNX.2.00.0908101205120.27553@iabervon.org>
On Mon, 10 Aug 2009, Daniel Barkalow wrote:
> > > In order to support this, there just needs to be a call to check whether
> > > "remote-<something>" is an available git command (without running it or
> > > giving an error), and the helper code should be used if it is. This is
> > > actually required so that people with workstations whose domain is
> > > .kernel.org and who have cloned "master:/home/linus/something.git" don't
> > > start getting "remote-master isn't a git command" errors (that is,
> > > misinterpreting ssh-format location hostnames as helper names. Johan,
> > > perhaps you could write that for your CVS helper?
> >
> > Sorry, not following you here. Write exactly what?
> >
> > - The code in the transport layer for checking if "remote-<something>"
> > is an available git command?
>
> That's what I was thinking.
Ok, I've spent way too much time on this, so if this doesn't cut it, I leave it
up to someone else to pick up the pieces.
The following patch series implements what I understand to be the current
consensus (or at least a good compromise) in this thread:
- There are two ways to indicate that a remote helper should be used:
1. remote.foo.vcs = <something>
2. remote.foo.url starts with "<something>:"
If both are present, remote.foo.vcs is preferred.
- Teach transport_helper_init() to check if "remote-<something>" is an
available git command. If so, use it. If not, gracefully abort the
transport-helper setup, and fall back to the "native" transport code.
- Skip the transport-helper code is the remote is obviously "native" (i.e.
URL starts with "git:"/"file:"/"ssh:"/"rsync:")
AFAICS this should make Daniel happy because his P4 setup will still work, and
it should also make Dscho happy, since he can tell people to
"git clone cvs::pserver:anonymous@cool.haxx.se:/cvsroot/curl#curl"
(of course, this depends on the CVS helper supporting remote.foo.url, which it
will, in a future iteration)
The non-trivial part of the series is in patch #5.
Implementing the rsync handling as another remote helper program is left as an
exercise for the reader...
Have fun! :)
...Johan
Johan Herland (6):
Minor unrelated fixes
transport_get(): Don't SEGFAULT on missing url
Move setup of curl remote helper from transport.c to transport-helper.c
Add is_git_command_or_alias() for checking availability of a given git command
Let transport_helper_init() decide if a remote helper program can be used
Add testcase to verify handling of missing remote helper programs
help.c | 23 ++++++++++++-
help.h | 2 +
t/t5590-remote-helper-missing.sh | 56 +++++++++++++++++++++++++++++++
transport-helper.c | 67 +++++++++++++++++++++++++++++++++++--
transport.c | 56 ++++++-------------------------
5 files changed, 154 insertions(+), 50 deletions(-)
create mode 100755 t/t5590-remote-helper-missing.sh
^ permalink raw reply
* [RFC/PATCH 4/6] Add is_git_command_or_alias() for checking availability of a given git command
From: Johan Herland @ 2009-08-11 10:10 UTC (permalink / raw)
To: git; +Cc: Johan Herland, barkalow, gitster, benji, Johannes.Schindelin
In-Reply-To: <alpine.LNX.2.00.0908101205120.27553@iabervon.org>
The transport-helper mechanism requires us to gracefully handle the case
where a git command is not available for some reason.
This patch introduces a simple function for querying the availability of a
git command, without attempting to execute said command.
The new function is very similar to the static is_git_command() function in
builtin-help.c, except that this function also accepts a matching alias.
Signed-off-by: Johan Herland <johan@herland.net>
---
help.c | 21 +++++++++++++++++++++
help.h | 2 ++
2 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/help.c b/help.c
index 994561d..a616277 100644
--- a/help.c
+++ b/help.c
@@ -296,6 +296,27 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
old->names = NULL;
}
+int is_git_command_or_alias(const char *cmd)
+{
+ struct cmdnames main_cmds, other_cmds;
+
+ memset(&main_cmds, 0, sizeof(main_cmds));
+ memset(&other_cmds, 0, sizeof(other_cmds));
+ memset(&aliases, 0, sizeof(aliases));
+
+ git_config(git_unknown_cmd_config, NULL);
+
+ load_command_list("git-", &main_cmds, &other_cmds);
+
+ add_cmd_list(&main_cmds, &aliases);
+ add_cmd_list(&main_cmds, &other_cmds);
+ qsort(main_cmds.names, main_cmds.cnt,
+ sizeof(main_cmds.names), cmdname_compare);
+ uniq(&main_cmds);
+
+ return is_in_cmdlist(&main_cmds, cmd);
+}
+
const char *help_unknown_cmd(const char *cmd)
{
int i, n, best_similarity = 0;
diff --git a/help.h b/help.h
index 56bc154..6c43452 100644
--- a/help.h
+++ b/help.h
@@ -26,4 +26,6 @@ int is_in_cmdlist(struct cmdnames *c, const char *s);
void list_commands(const char *title, struct cmdnames *main_cmds,
struct cmdnames *other_cmds);
+int is_git_command_or_alias(const char *cmd);
+
#endif /* HELP_H */
--
1.6.4.rc3.138.ga6b98.dirty
^ permalink raw reply related
* [RFC/PATCH 6/6] Add testcase to verify handling of missing remote helper programs
From: Johan Herland @ 2009-08-11 10:10 UTC (permalink / raw)
To: git; +Cc: Johan Herland, barkalow, gitster, benji, Johannes.Schindelin
In-Reply-To: <alpine.LNX.2.00.0908101205120.27553@iabervon.org>
Signed-off-by: Johan Herland <johan@herland.net>
---
t/t5590-remote-helper-missing.sh | 56 ++++++++++++++++++++++++++++++++++++++
1 files changed, 56 insertions(+), 0 deletions(-)
create mode 100755 t/t5590-remote-helper-missing.sh
diff --git a/t/t5590-remote-helper-missing.sh b/t/t5590-remote-helper-missing.sh
new file mode 100755
index 0000000..3bc2bc2
--- /dev/null
+++ b/t/t5590-remote-helper-missing.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+test_description='test graceful failure when missing remote helper program'
+. ./test-lib.sh
+
+test_expect_success 'setup repository' '
+ echo content >file &&
+ git add file &&
+ git commit -m one &&
+ git config remote.missing.vcs foo &&
+ git remote add missing2 foo:/nonexisting/path
+'
+
+test_expect_success 'fetch changes from "missing" remote' '
+ cat <<EOF >expect &&
+warning: Could not find remote helper command "git remote-foo". Assuming native remote.
+EOF
+ ! git fetch missing >actual 2>&1 &&
+ head -n1 actual >actual.first &&
+ test_cmp expect actual.first
+'
+
+test_expect_success 'fetch changes from "missing2" remote' '
+ cat <<EOF >expect &&
+warning: Could not find remote helper command "git remote-foo". Assuming native remote.
+EOF
+ ! git fetch missing2 >actual 2>&1 &&
+ head -n1 actual >actual.first &&
+ test_cmp expect actual.first
+'
+
+test_expect_success 'push changes to "missing" remote' '
+ echo "more content" >>file &&
+ git add file &&
+ git commit -m two &&
+ cat <<EOF >expect &&
+warning: Could not find remote helper command "git remote-foo". Assuming native remote.
+EOF
+ ! git push --all missing >actual 2>&1 &&
+ head -n1 actual >actual.first &&
+ test_cmp expect actual.first
+'
+
+test_expect_success 'push changes to "missing2" remote' '
+ echo "even more content" >>file &&
+ git add file &&
+ git commit -m three &&
+ cat <<EOF >expect &&
+warning: Could not find remote helper command "git remote-foo". Assuming native remote.
+EOF
+ ! git push --all missing2 >actual 2>&1 &&
+ head -n1 actual >actual.first &&
+ test_cmp expect actual.first
+'
+
+test_done
--
1.6.4.rc3.138.ga6b98.dirty
^ permalink raw reply related
* [RFC/PATCH 2/6] transport_get(): Don't SEGFAULT on missing url
From: Johan Herland @ 2009-08-11 10:10 UTC (permalink / raw)
To: git; +Cc: Johan Herland, barkalow, gitster, benji, Johannes.Schindelin
In-Reply-To: <alpine.LNX.2.00.0908101205120.27553@iabervon.org>
Signed-off-by: Johan Herland <johan@herland.net>
---
transport.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/transport.c b/transport.c
index 19f330a..26d9999 100644
--- a/transport.c
+++ b/transport.c
@@ -820,14 +820,15 @@ struct transport *transport_get(struct remote *remote, const char *url)
return ret;
}
- if (!prefixcmp(url, "rsync:")) {
+ if (url && !prefixcmp(url, "rsync:")) {
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
- } else if (!prefixcmp(url, "http://")
- || !prefixcmp(url, "https://")
- || !prefixcmp(url, "ftp://")) {
+ } else if (url
+ && (!prefixcmp(url, "http://")
+ || !prefixcmp(url, "https://")
+ || !prefixcmp(url, "ftp://"))) {
transport_helper_init(ret);
#ifdef NO_CURL
error("git was compiled without libcurl support.");
@@ -835,7 +836,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->push = curl_transport_push;
#endif
- } else if (is_local(url) && is_file(url)) {
+ } else if (url && is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
ret->data = data;
ret->get_refs_list = get_refs_from_bundle;
--
1.6.4.rc3.138.ga6b98.dirty
^ permalink raw reply related
* [RFC/PATCH 5/6] Let transport_helper_init() decide if a remote helper program can be used
From: Johan Herland @ 2009-08-11 10:10 UTC (permalink / raw)
To: git; +Cc: Johan Herland, barkalow, gitster, benji, Johannes.Schindelin
In-Reply-To: <alpine.LNX.2.00.0908101205120.27553@iabervon.org>
Teach the transport-helper mechanism to verify that the remote helper
program is available, before finalizing the transport setup.
If the remote helper is NOT available, transport_helper_init() returns -1,
and transport_get() falls back to trying a native transport.
This patch introduces a subtle, but important change in the handling of
remotes and their URLs:
Before this patch, we only invoke transport_helper_init() _after_ we find
that the transport-helper mechanism is appropriate for this remote
(i.e. the remote is "foreign", or is handled by the curl helper).
This patch moves the decision point into transport_helper_init(): If the
remote is not obviously using a native transport (URL starts with "file:",
"git:" or "ssh:"), then we first call transport_helper_init(), and only if
it returns error (meaning that no appropriate remote helper program was
found) do we fall back to native transport handling.
Signed-off-by: Johan Herland <johan@herland.net>
---
transport-helper.c | 22 ++++++++++++++++++++--
transport.c | 11 ++++++-----
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index d3ce984..de30727 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -5,6 +5,7 @@
#include "commit.h"
#include "diff.h"
#include "revision.h"
+#include "help.h"
struct helper_data
{
@@ -279,11 +280,18 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
int transport_helper_init(struct transport *transport)
{
- struct helper_data *data = xcalloc(sizeof(*data), 1);
+ struct helper_data *data;
+ struct strbuf buf = STRBUF_INIT;
+ char *cmd;
+
+ if (!transport->remote)
+ return -1;
+ data = xcalloc(sizeof(*data), 1);
if (transport->remote->foreign_vcs) {
data->name = xstrdup(transport->remote->foreign_vcs);
- transport->url = transport->remote->foreign_vcs;
+ if (!transport->url)
+ transport->url = transport->remote->foreign_vcs;
} else {
char *eom = strchr(transport->url, ':');
if (!eom) {
@@ -293,6 +301,16 @@ int transport_helper_init(struct transport *transport)
data->name = xstrndup(transport->url, eom - transport->url);
}
+ strbuf_addf(&buf, "remote-%s", data->name);
+ cmd = strbuf_detach(&buf, NULL);
+ if (!is_git_command_or_alias(cmd)) {
+ warning("Could not find remote helper command \"git %s\". Assuming native remote.", cmd);
+ free(cmd);
+ free(data->name);
+ free(data);
+ return -1;
+ }
+
transport->data = data;
transport->get_refs_list = get_refs_list;
transport->fetch = fetch;
diff --git a/transport.c b/transport.c
index 81a28bc..b7033eb 100644
--- a/transport.c
+++ b/transport.c
@@ -794,11 +794,12 @@ struct transport *transport_get(struct remote *remote, const char *url)
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
- } else if (!url
- || !prefixcmp(url, "http://")
- || !prefixcmp(url, "https://")
- || !prefixcmp(url, "ftp://")) {
- transport_helper_init(ret);
+ } else if ((!url
+ || (prefixcmp(url, "git:")
+ && prefixcmp(url, "ssh:")
+ && prefixcmp(url, "file:")))
+ && !transport_helper_init(ret)) {
+ /* no-op, ret is initialized by transport_helper_init() */
} else if (url && is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
--
1.6.4.rc3.138.ga6b98.dirty
^ permalink raw reply related
* [RFC/PATCH 3/6] Move setup of curl remote helper from transport.c to transport-helper.c
From: Johan Herland @ 2009-08-11 10:10 UTC (permalink / raw)
To: git; +Cc: Johan Herland, barkalow, gitster, benji, Johannes.Schindelin
In-Reply-To: <alpine.LNX.2.00.0908101205120.27553@iabervon.org>
Since the curl transport is now launched by the transport-helper mechanism,
it makes sense to move the remaining curl-related code (i.e.
curl_transport_push()) from transport.c into transport-helper.c.
The patch also consolidates the two transport_helper_init() call sites
("foreign" helper and curl helper).
Signed-off-by: Johan Herland <johan@herland.net>
---
transport-helper.c | 39 +++++++++++++++++++++++++++++++++++++++
transport.c | 48 ++++++------------------------------------------
2 files changed, 45 insertions(+), 42 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index a901630..d3ce984 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -249,6 +249,34 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
return ret;
}
+#ifndef NO_CURL
+static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
+{
+ const char **argv;
+ int argc;
+
+ if (flags & TRANSPORT_PUSH_MIRROR)
+ return error("http transport does not support mirror mode");
+
+ argv = xmalloc((refspec_nr + 12) * sizeof(char *));
+ argv[0] = "http-push";
+ argc = 1;
+ if (flags & TRANSPORT_PUSH_ALL)
+ argv[argc++] = "--all";
+ if (flags & TRANSPORT_PUSH_FORCE)
+ argv[argc++] = "--force";
+ if (flags & TRANSPORT_PUSH_DRY_RUN)
+ argv[argc++] = "--dry-run";
+ if (flags & TRANSPORT_PUSH_VERBOSE)
+ argv[argc++] = "--verbose";
+ argv[argc++] = transport->url;
+ while (refspec_nr--)
+ argv[argc++] = *refspec++;
+ argv[argc] = NULL;
+ return !!run_command_v_opt(argv, RUN_GIT_CMD);
+}
+#endif
+
int transport_helper_init(struct transport *transport)
{
struct helper_data *data = xcalloc(sizeof(*data), 1);
@@ -269,5 +297,16 @@ int transport_helper_init(struct transport *transport)
transport->get_refs_list = get_refs_list;
transport->fetch = fetch;
transport->disconnect = disconnect_helper;
+
+ if (!strcmp(data->name, "http")
+ || !strcmp(data->name, "https")
+ || !strcmp(data->name, "ftp")) {
+#ifdef NO_CURL
+ error("git was compiled without libcurl support.");
+#else
+ transport->push = curl_transport_push;
+#endif
+ }
+
return 0;
}
diff --git a/transport.c b/transport.c
index 26d9999..81a28bc 100644
--- a/transport.c
+++ b/transport.c
@@ -349,35 +349,6 @@ static int rsync_transport_push(struct transport *transport,
return result;
}
-#ifndef NO_CURL
-static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
-{
- const char **argv;
- int argc;
-
- if (flags & TRANSPORT_PUSH_MIRROR)
- return error("http transport does not support mirror mode");
-
- argv = xmalloc((refspec_nr + 12) * sizeof(char *));
- argv[0] = "http-push";
- argc = 1;
- if (flags & TRANSPORT_PUSH_ALL)
- argv[argc++] = "--all";
- if (flags & TRANSPORT_PUSH_FORCE)
- argv[argc++] = "--force";
- if (flags & TRANSPORT_PUSH_DRY_RUN)
- argv[argc++] = "--dry-run";
- if (flags & TRANSPORT_PUSH_VERBOSE)
- argv[argc++] = "--verbose";
- argv[argc++] = transport->url;
- while (refspec_nr--)
- argv[argc++] = *refspec++;
- argv[argc] = NULL;
- return !!run_command_v_opt(argv, RUN_GIT_CMD);
-}
-
-#endif
-
struct bundle_transport_data {
int fd;
struct bundle_header header;
@@ -815,26 +786,19 @@ struct transport *transport_get(struct remote *remote, const char *url)
url = remote->url[0];
ret->url = url;
- if (remote && remote->foreign_vcs) {
- transport_helper_init(ret);
- return ret;
- }
+ if (remote && remote->foreign_vcs)
+ url = NULL;
if (url && !prefixcmp(url, "rsync:")) {
ret->get_refs_list = get_refs_via_rsync;
ret->fetch = fetch_objs_via_rsync;
ret->push = rsync_transport_push;
- } else if (url
- && (!prefixcmp(url, "http://")
- || !prefixcmp(url, "https://")
- || !prefixcmp(url, "ftp://"))) {
+ } else if (!url
+ || !prefixcmp(url, "http://")
+ || !prefixcmp(url, "https://")
+ || !prefixcmp(url, "ftp://")) {
transport_helper_init(ret);
-#ifdef NO_CURL
- error("git was compiled without libcurl support.");
-#else
- ret->push = curl_transport_push;
-#endif
} else if (url && is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
--
1.6.4.rc3.138.ga6b98.dirty
^ permalink raw reply related
* [PATCH] [TRIVIAL] Documentation: merge: one <remote> is required
From: Paul Bolle @ 2009-08-11 13:03 UTC (permalink / raw)
To: Junio C Hamano, git
merge only requires one <remote>, so "<remote>..." should be used in the
synopsis (and not "<remote> <remote>...").
Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
---
Documentation/git-merge.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index c04ae73..af68d69 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
- [-m <msg>] <remote> <remote>...
+ [-m <msg>] <remote>...
'git merge' <msg> HEAD <remote>...
DESCRIPTION
--
1.6.4
^ permalink raw reply related
* [PATCH] [TRIVIAL] Documentation: add: <filepattern>... is optional
From: Paul Bolle @ 2009-08-11 13:03 UTC (permalink / raw)
To: Junio C Hamano, git
<filepattern>... is optional (e.g. when the --all or --update
options are used) so use square brackets in the synopsis.
Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
---
Documentation/git-add.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index ab1943c..e67b7e8 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -10,7 +10,7 @@ SYNOPSIS
[verse]
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
[--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
- [--refresh] [--ignore-errors] [--] <filepattern>...
+ [--refresh] [--ignore-errors] [--] [<filepattern>...]
DESCRIPTION
-----------
--
1.6.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).