* [PATCH] Fix usage of carets in git-rev-parse(1)
From: Jonas Fonseca @ 2005-10-05 23:42 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Alan Chandler, git
In-Reply-To: <7v7jcrh7wu.fsf@assigned-by-dhcp.cox.net>
... but using a {caret} attribute.
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
---
Junio C Hamano <junkio@cox.net> wrote Wed, Oct 05, 2005:
> Alan Chandler <alan@chandlerfamily.org.uk> writes:
>
> > "A suffix ~<n> to a revision parameter means the commit object that is
> > the <n>th generation grand-parent of the named commit object, following only
> > the first parent. I.e. rev~3 is equivalent to rev^ which is equivalent to
> > rev11^1."
> >
> > Why is rev~3 equivalent to rev^, surely it is equivalent to rev^^^
> >
> > Why is rev~3 equivalent to rev11^1, should that not be rev^1^1^1
>
> Sorry, for not knowing how to do that properly in Asciidoc ;-).
I think something like the following will do ...
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -7,6 +7,9 @@
# Show GIT link as: <command>(<section>); if section is defined, else just show
# the command.
+[attributes]
+caret=^
+
ifdef::backend-docbook[]
[gitlink-inlinemacro]
{0%{target}}
@@ -19,3 +22,5 @@ ifdef::backend-xhtml11[]
[gitlink-inlinemacro]
<a href="{target}.html">{target}{0?({0})}</a>
endif::backend-xhtml11[]
+
+
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -54,13 +54,13 @@ OPTIONS
`git-diff-\*`).
--not::
- When showing object names, prefix them with '^' and
- strip '^' prefix from the object names that already have
+ When showing object names, prefix them with '{caret}' and
+ strip '{caret}' prefix from the object names that already have
one.
--symbolic::
Usually the object names are output in SHA1 form (with
- possible '^' prefix); this option makes them output in a
+ possible '{caret}' prefix); this option makes them output in a
form as close to the original input as possible.
@@ -93,22 +93,23 @@ what is called an 'extended SHA1' syntax
happen to have both heads/master and tags/master, you can
explicitly say 'heads/master' to tell GIT which one you mean.
-* A suffix '^' to a revision parameter means the first parent of
- that commit object. '^<n>' means the <n>th parent (i.e.
- 'rev^'
- is equivalent to 'rev^1'). As a special rule,
- 'rev^0' means the commit itself and is used when 'rev' is the
+* A suffix '{caret}' to a revision parameter means the first parent of
+ that commit object. '{caret}<n>' means the <n>th parent (i.e.
+ 'rev{caret}'
+ is equivalent to 'rev{caret}1'). As a special rule,
+ 'rev{caret}0' means the commit itself and is used when 'rev' is the
object name of a tag object that refers to a commit object.
* A suffix '~<n>' to a revision parameter means the commit
object that is the <n>th generation grand-parent of the named
commit object, following only the first parent. I.e. rev~3 is
- equivalent to rev^^^ which is equivalent to rev^1^1^1.
+ equivalent to rev{caret}{caret}{caret} which is equivalent to\
+ rev{caret}1{caret}1{caret}1.
-'git-rev-parse' also accepts a prefix '^' to revision parameter,
+'git-rev-parse' also accepts a prefix '{caret}' to revision parameter,
which is passed to 'git-rev-list'. Two revision parameters
concatenated with '..' is a short-hand for writing a range
-between them. I.e. 'r1..r2' is equivalent to saying '^r1 r2'
+between them. I.e. 'r1..r2' is equivalent to saying '{caret}r1 r2'
Author
--
Jonas Fonseca
^ permalink raw reply
* Re: Confused as to the correct syntax
From: Alan Chandler @ 2005-10-05 23:33 UTC (permalink / raw)
To: git
In-Reply-To: <7v7jcrh7wu.fsf@assigned-by-dhcp.cox.net>
On Thursday 06 Oct 2005 00:16, Junio C Hamano wrote:
> Alan Chandler <alan@chandlerfamily.org.uk> writes:
> > "A suffix ~<n> to a revision parameter means the commit object that
> > is the <n>th generation grand-parent of the named commit object,
> > following only the first parent. I.e. rev~3 is equivalent to rev^ which
> > is equivalent to rev11^1."
> >
> > Why is rev~3 equivalent to rev^, surely it is equivalent to rev^^^
> >
> > Why is rev~3 equivalent to rev11^1, should that not be rev^1^1^1
>
> Sorry, for not knowing how to do that properly in Asciidoc ;-).
>
> The source to the man page and HTML page reads like this:
>
> * A suffix '~<n>' to a revision parameter means the commit
> object that is the <n>th generation grand-parent of the named
> commit object, following only the first parent. I.e. rev~3 is
> equivalent to rev^^^ which is equivalent to rev^1^1^1.
No the HTML page is screwed up too.
--
Alan Chandler
http://www.chandlerfamily.org.uk
Open Source. It's the difference between trust and antitrust.
^ permalink raw reply
* Re: Notes and questions while reading the documentation
From: Junio C Hamano @ 2005-10-05 23:30 UTC (permalink / raw)
To: Christian Meder; +Cc: git
In-Reply-To: <1128549966.11363.29.camel@localhost>
Christian Meder <chris@absolutegiganten.org> writes:
> * a lot of the manpages include something like "v0.1, June 2005" in the
> header; these versions tags are pretty obscure to interpret, timestamp
> when last edited ? version of the manpage ? version of git when the
> manpage was included ? maturity the author assigned to the content ?
> If these tags don't follow some sane schema they should be removed.
I think the original intent was the last modification datestamp
and the version of the documentation, but I agree it should be
removed. I do not think they show on the HTML version, nor man
pages, although I have to admit that I haven't looked at
generated manpages for some time.
> * git-applymbox: -q for interactivity seems like a strange choice, ok I
> knew -i for interactive and -q for quiet but -q for interactive editing
> is _not_ really intuitive
Last night I felt the same way, and an rewrite [*1*] of
applymbox I am working on uses '-i' instead. If users do not
object, I would vote for changing applymbox to use '-i' as well.
The user community consensus does not have to be unanimous, but
anybody who has linux kernel tree on kernel.org servers has a
veto on this, I should say. It's the tool they use every day.
> * the usage of git, Git and GIT isn't consistent in the documentation.
> I'd vote for only using git.
Sounds sane. What would we do if we need to start sentences with it?
> * git-clone says that http transport is not supported yet I used it to
> clone the git repo from kernel.org yesterday. Should the documentation
> get updated ?
Thanks for noticing. Yes, now HTTP can handle both of the
trickier setups (packed, and alternates); credit goes to Daniel.
> * the manpage synopsises aren't consistent wrt command naming; it's "git
> commit" but "git-branch"; I guess all the manpages should reference
> their commands as "git-x" and not "git x"
Agreed.
Again, thanks for taking the time to do this.
[Footnote]
*1* Why rewrite? One reason was I was afraid to break things
for Linus ;-). And I wanted to add a bit more interactivity and
restartability. The ultimate goal is to make 'git-rebase' and
'git-cherry-pick' faster and easier to use. The idea is not to
always do 3-way merge, but essentailly feed format-patch output
(now it can do --stdout) into the new applymbox, and when patch
applies cleanly things will go faster, otherwise it will fall
back to 3-way merge behaviour.
^ permalink raw reply
* Re: Confused as to the correct syntax
From: Junio C Hamano @ 2005-10-05 23:16 UTC (permalink / raw)
To: Alan Chandler; +Cc: git
In-Reply-To: <200510052350.07217.alan@chandlerfamily.org.uk>
Alan Chandler <alan@chandlerfamily.org.uk> writes:
> "A suffix ~<n> to a revision parameter means the commit object that is
> the <n>th generation grand-parent of the named commit object, following only
> the first parent. I.e. rev~3 is equivalent to rev^ which is equivalent to
> rev11^1."
>
> Why is rev~3 equivalent to rev^, surely it is equivalent to rev^^^
>
> Why is rev~3 equivalent to rev11^1, should that not be rev^1^1^1
Sorry, for not knowing how to do that properly in Asciidoc ;-).
The source to the man page and HTML page reads like this:
* A suffix '~<n>' to a revision parameter means the commit
object that is the <n>th generation grand-parent of the named
commit object, following only the first parent. I.e. rev~3 is
equivalent to rev^^^ which is equivalent to rev^1^1^1.
^ permalink raw reply
* Confused as to the correct syntax
From: Alan Chandler @ 2005-10-05 22:50 UTC (permalink / raw)
To: git
The man page for git-rev-parse talks about the way to specify commits back
from a named commit object. The following text in this man page tries to
explain it, but it has confused me more
"A suffix ~<n> to a revision parameter means the commit object that is
the <n>th generation grand-parent of the named commit object, following only
the first parent. I.e. rev~3 is equivalent to rev^ which is equivalent to
rev11^1."
Why is rev~3 equivalent to rev^, surely it is equivalent to rev^^^
Why is rev~3 equivalent to rev11^1, should that not be rev^1^1^1
I don't understand the syntax here - so was looking it up in the man page. Is
there an error in the page or have I misunderstood something.
--
Alan Chandler
http://www.chandlerfamily.org.uk
Open Source. It's the difference between trust and antitrust.
^ permalink raw reply
* Re: clone: I'm only doing a max of 256 requests
From: Linus Torvalds @ 2005-10-05 22:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, linux-kernel
In-Reply-To: <7vy857iqzh.fsf@assigned-by-dhcp.cox.net>
On Wed, 5 Oct 2005, Junio C Hamano wrote:
>
> Hmph. I was reading linux-2.6/fs/exec.c::copy_strings(), but I
> do not see any such size limit (other than exceeding the total
> machine memory size, probably reported by alloc_page() failing)
> imposed there. Am I looking at the wrong place?
Look for "MAX_ARG_PAGES".
Ie the limit is about 128kB by default (32 pages). Note that that includes
not just arguments, but environment.
Linus
^ permalink raw reply
* Re: clone: I'm only doing a max of 256 requests
From: Linus Torvalds @ 2005-10-05 22:45 UTC (permalink / raw)
To: Andy Isaacson; +Cc: git
In-Reply-To: <20051005191300.GC17475@hexapodia.org>
On Wed, 5 Oct 2005, Andy Isaacson wrote:
>
> Trying to do a local clone of the linux-mips.org git repo:
>
> % git clone /home/adi/linux/git/lmo/linux foo
> defaulting to local storage area
> fatal: I'm only doing a max of 256 requests
The pack upload has a totally arbitrary limit of 256 heads.
> I got git/lmo/linux from http://www.linux-mips.org/pub/scm/linux.git.
Heh. And:
git ls-remote http://www.linux-mips.org/pub/scm/linux.git | wc -l
returns "295". Seems to have all the old bk history in it.
> Am I doing something wrong, or what?
No, just change the "MAX_NEEDS" define from 256 to some larger value.
There's no real reason for the limit, except that maybe we should have
some dynamic allocation for this.
Linus
^ permalink raw reply
* Re: clone: I'm only doing a max of 256 requests
From: Vincent Hanquez @ 2005-10-05 22:27 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, linux-kernel
In-Reply-To: <7vy857iqzh.fsf@assigned-by-dhcp.cox.net>
On Wed, Oct 05, 2005 at 02:38:42PM -0700, Junio C Hamano wrote:
> Hmph. I was reading linux-2.6/fs/exec.c::copy_strings(), but I
> do not see any such size limit (other than exceeding the total
> machine memory size, probably reported by alloc_page() failing)
> imposed there. Am I looking at the wrong place?
well at least the len of argv is limited by ~32K (i386) by:
bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
...
bprm->argc = count(argv, bprm->p / sizeof(void *));
--
Vincent Hanquez
^ permalink raw reply
* Re: [PATCH] Some typos and light editing of various manpages
From: Junio C Hamano @ 2005-10-05 22:09 UTC (permalink / raw)
To: Christian Meder; +Cc: git
In-Reply-To: <1128548890.11363.11.camel@localhost>
Thanks. I appreciate these fixes very much. Will apply.
^ permalink raw reply
* Notes and questions while reading the documentation
From: Christian Meder @ 2005-10-05 22:06 UTC (permalink / raw)
To: git
Hi,
while (proof-)reading the Documentation I noted down some remarks and
questions:
* a lot of the manpages include something like "v0.1, June 2005" in the
header; these versions tags are pretty obscure to interpret, timestamp
when last edited ? version of the manpage ? version of git when the
manpage was included ? maturity the author assigned to the content ?
If these tags don't follow some sane schema they should be removed.
* git-applymbox: -q for interactivity seems like a strange choice, ok I
knew -i for interactive and -q for quiet but -q for interactive editing
is _not_ really intuitive
* the usage of git, Git and GIT isn't consistent in the documentation.
I'd vote for only using git.
* git-clone says that http transport is not supported yet I used it to
clone the git repo from kernel.org yesterday. Should the documentation
get updated ?
* the manpage synopsises aren't consistent wrt command naming; it's "git
commit" but "git-branch"; I guess all the manpages should reference
their commands as "git-x" and not "git x"
Greetings,
Christian
--
Christian Meder, email: chris@absolutegiganten.org
The Way-Seeking Mind of a tenzo is actualized
by rolling up your sleeves.
(Eihei Dogen Zenji)
^ permalink raw reply
* Re: [PATCH] Write .editmsg in GIT_DIR to avoid being in git-status.
From: Junio C Hamano @ 2005-10-05 21:54 UTC (permalink / raw)
To: sbejar; +Cc: git
In-Reply-To: <87achnq4z7.fsf@gmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=iso-2022-jp-2, Size: 1116 bytes --]
Santi B^[.A^[Nijar <sbejar@gmail.com> writes:
> It appears in the git-status output during a git-commit if you have
> something in info/exclude.
... which does not worry me too much; you'll get used to it ;-).
> Also for .cmitmsg and .cmitchk to make git-commit work
> in read-only working trees.
If a working tree is read-only, I wonder what you are committing.
It might not be a bad idea to think about this a bit more before
actually coding. You are moving things out of the working tree
root level, which is a valid thing to do when worrying about a
repository (or working tree) that you do not have write access
to. We've had a fix similar to this for temporary files used by
diff commands, which moved them to $TMPDIR or something like
that. If the working tree root level is not writable for you,
is it valid/reasonable to assume that $GIT_DIR is? Are there
better places? E.g. perhaps $HOME/.gittmp/?
> ret="$?"
> -rm -f .cmitmsg .editmsg .cmitchk
> +rm -f "$GIT_DIR"/{.cmitmsg,.editmsg,.cmitchk}
Please do not do "{a,b,c}". I think ksh can grok the rest of
the git-commit.sh code, but not this.
^ permalink raw reply
* [PATCH] upload-pack: Do not choke on too many heads request.
From: Junio C Hamano @ 2005-10-05 21:51 UTC (permalink / raw)
To: Andy Isaacson; +Cc: git
In-Reply-To: <20051005191300.GC17475@hexapodia.org>
Cloning from a repository with more than 256 refs (heads and tags
included) will choke, because upload-pack has a built-in limit of
feeding not more than MAX_NEEDS (currently 256) heads to underlying
git-rev-list. This is a problem when cloning a repository with many
tags, like http://www.linux-mips.org/pub/scm/linux.git, which has 290+
tags.
This commit introduces a new flag, --all, to git-rev-list, to include
all refs in the repository. Updated upload-pack detects requests that
ask more than MAX_NEEDS refs, and sends everything back instead.
We may probably want to tweak the definitions of MAX_NEEDS and
MAX_HAS, but that is a separate topic.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Andy Isaacson <adi@hexapodia.org> writes:
> Trying to do a local clone of the linux-mips.org git repo:
>
> % git clone /home/adi/linux/git/lmo/linux foo
> defaulting to local storage area
> fatal: I'm only doing a max of 256 requests
> % git -v
> git version 0.99.8.GIT
>
> I got git/lmo/linux from http://www.linux-mips.org/pub/scm/linux.git.
>
> Am I doing something wrong, or what?
You are not doing anything wrong. Please try this patch.
rev-list.c | 21 +++++++++++++++++++++
rev-parse.c | 1 +
upload-pack.c | 50 ++++++++++++++++++++++++++++++++++----------------
3 files changed, 56 insertions(+), 16 deletions(-)
applies-to: dc721a63b8221995616e3013de11e71d94da01ef
e091eb93258f05a58bc5d1c60f058f5f57dd92b6
diff --git a/rev-list.c b/rev-list.c
--- a/rev-list.c
+++ b/rev-list.c
@@ -1,4 +1,5 @@
#include "cache.h"
+#include "refs.h"
#include "tag.h"
#include "commit.h"
#include "tree.h"
@@ -489,6 +490,22 @@ static void handle_one_commit(struct com
commit_list_insert(com, lst);
}
+/* for_each_ref() callback does not allow user data -- Yuck. */
+static struct commit_list **global_lst;
+
+static int include_one_commit(const char *path, const unsigned char *sha1)
+{
+ struct commit *com = get_commit_reference(path, 0);
+ handle_one_commit(com, global_lst);
+ return 0;
+}
+
+static void handle_all(struct commit_list **lst)
+{
+ global_lst = lst;
+ for_each_ref(include_one_commit);
+ global_lst = NULL;
+}
int main(int argc, char **argv)
{
@@ -542,6 +559,10 @@ int main(int argc, char **argv)
bisect_list = 1;
continue;
}
+ if (!strcmp(arg, "--all")) {
+ handle_all(&list);
+ continue;
+ }
if (!strcmp(arg, "--objects")) {
tag_objects = 1;
tree_objects = 1;
diff --git a/rev-parse.c b/rev-parse.c
--- a/rev-parse.c
+++ b/rev-parse.c
@@ -32,6 +32,7 @@ static int revs_count = 0;
static int is_rev_argument(const char *arg)
{
static const char *rev_args[] = {
+ "--all",
"--bisect",
"--header",
"--max-age=",
diff --git a/upload-pack.c b/upload-pack.c
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -30,10 +30,18 @@ static void create_pack_file(void)
if (!pid) {
int i;
- int args = nr_has + nr_needs + 5;
- char **argv = xmalloc(args * sizeof(char *));
- char *buf = xmalloc(args * 45);
- char **p = argv;
+ int args;
+ char **argv;
+ char *buf;
+ char **p;
+
+ if (MAX_NEEDS <= nr_needs)
+ args = nr_has + 10;
+ else
+ args = nr_has + nr_needs + 5;
+ argv = xmalloc(args * sizeof(char *));
+ buf = xmalloc(args * 45);
+ p = argv;
dup2(fd[1], 1);
close(0);
@@ -41,10 +49,14 @@ static void create_pack_file(void)
close(fd[1]);
*p++ = "git-rev-list";
*p++ = "--objects";
- for (i = 0; i < nr_needs; i++) {
- *p++ = buf;
- memcpy(buf, sha1_to_hex(needs_sha1[i]), 41);
- buf += 41;
+ if (MAX_NEEDS <= nr_needs)
+ *p++ = "--all";
+ else {
+ for (i = 0; i < nr_needs; i++) {
+ *p++ = buf;
+ memcpy(buf, sha1_to_hex(needs_sha1[i]), 41);
+ buf += 41;
+ }
}
for (i = 0; i < nr_has; i++) {
*p++ = buf;
@@ -129,18 +141,24 @@ static int receive_needs(void)
needs = 0;
for (;;) {
+ unsigned char dummy[20], *sha1_buf;
len = packet_read_line(0, line, sizeof(line));
if (!len)
return needs;
- /*
- * This is purely theoretical right now: git-fetch-pack only
- * ever asks for a single HEAD
- */
- if (needs >= MAX_NEEDS)
- die("I'm only doing a max of %d requests", MAX_NEEDS);
- if (strncmp("want ", line, 5) || get_sha1_hex(line+5, needs_sha1[needs]))
- die("git-upload-pack: protocol error, expected to get sha, not '%s'", line);
+ sha1_buf = dummy;
+ if (needs == MAX_NEEDS) {
+ fprintf(stderr,
+ "warning: supporting only a max of %d requests. "
+ "sending everything instead.\n",
+ MAX_NEEDS);
+ }
+ else if (needs < MAX_NEEDS)
+ sha1_buf = needs_sha1[needs];
+
+ if (strncmp("want ", line, 5) || get_sha1_hex(line+5, sha1_buf))
+ die("git-upload-pack: protocol error, "
+ "expected to get sha, not '%s'", line);
needs++;
}
}
---
0.99.8.GIT
^ permalink raw reply
* [PATCH] Some typos and light editing of various manpages
From: Christian Meder @ 2005-10-05 21:48 UTC (permalink / raw)
To: git
Typos, light editing and clarifications.
Signed-off-by: Christian Meder <chris@absolutegiganten.org>
---
Christian Meder, email: chris@absolutegiganten.org
The Way-Seeking Mind of a tenzo is actualized
by rolling up your sleeves.
(Eihei Dogen Zenji)
diff --git a/Documentation/cvs-migration.txt b/Documentation/cvs-migration.txt
--- a/Documentation/cvs-migration.txt
+++ b/Documentation/cvs-migration.txt
@@ -24,7 +24,7 @@ The good news is that most people don't
people think it's a bug in CVS that makes it tag (and check in changes)
one file at a time. So most projects you'll ever see will use CVS
'as if' it was sane. In which case you'll find it very easy indeed to
-move over to Git.
+move over to git.
First off: this is not a git tutorial. See
link:tutorial.html[Documentation/tutorial.txt] for how git
@@ -229,7 +229,7 @@ does rename or copy would not show in th
"o-file.c", it would find the commit that changed the statement
when it was in "o-file.c".
-NOTE: The current versions of "git-diff-tree -C" is not eager
+NOTE: The current version of "git-diff-tree -C" is not eager
enough to find copies, and it will miss the fact that a-file.c
was created by copying o-file.c unless o-file.c was somehow
changed in the same commit.
diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt
--- a/Documentation/diff-format.txt
+++ b/Documentation/diff-format.txt
@@ -1,8 +1,8 @@
The output format from "git-diff-index", "git-diff-tree" and
"git-diff-files" are very similar.
-These commands all compare two sets of things; what are
-compared are different:
+These commands all compare two sets of things; what is
+compared differs:
git-diff-index <tree-ish>::
compares the <tree-ish> and the files on the filesystem.
@@ -46,7 +46,7 @@ That is, from the left to the right:
. path for "dst"; only exists for C or R.
. an LF or a NUL when '-z' option is used, to terminate the record.
-<sha1> is shown as all 0's if new is a file on the filesystem
+<sha1> is shown as all 0's if a file is new on the filesystem
and it is out of sync with the cache.
Example:
@@ -91,7 +91,7 @@ For a path that is added, removed, or mo
where:
<old|new>-file:: are files GIT_EXTERNAL_DIFF can use to read the
- contents of <old|ne>,
+ contents of <old|new>,
<old|new>-hex:: are the 40-hexdigit SHA1 hashes,
<old|new>-mode:: are the octal representation of the file modes.
@@ -121,12 +121,11 @@ The `a/` and `b/` filenames are the same
involved. Especially, even for a creation or a deletion,
`/dev/null` is _not_ used in place of `a/` or `b/` filenames.
+
-When rename/copy is involved, `file1` and `file2` shows the
+When rename/copy is involved, `file1` and `file2` show the
name of the source file of the rename/copy and the name of
the file that rename/copy produces, respectively.
-2. It is followed by extended header lines that are one or
- more of:
+2. It is followed by one or more extended header lines:
old mode <mode>
new mode <mode>
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -5,9 +5,8 @@
Synonym for "-p".
-r::
- Look recursively in subdirectories; this flag does not
- mean anything to commands other than "git-diff-tree";
- other diff commands always look at all the subdirectories.
+ Look recursively in subdirectories; only used by "git-diff-tree";
+ other diff commands always work recursively.
-z::
\0 line termination on output
@@ -28,26 +27,26 @@
Detect copies as well as renames.
--find-copies-harder::
- By default, -C option finds copies only if the original
- file of the copy was modified in the same changeset for
- performance reasons. This flag makes the command
+ For performance reasons, by default, -C option finds copies only
+ if the original file of the copy was modified in the same
+ changeset. This flag makes the command
inspect unmodified files as candidates for the source of
copy. This is a very expensive operation for large
projects, so use it with caution.
-l<num>::
-M and -C options require O(n^2) processing time where n
- in the number of potential rename/copy targets. This
+ is the number of potential rename/copy targets. This
option prevents rename/copy detection from running if
- the number of rename/copy targets exceed the specified
+ the number of rename/copy targets exceeds the specified
number.
-S<string>::
- Look for differences that contains the change in <string>.
+ Look for differences that contain the change in <string>.
--pickaxe-all::
When -S finds a change, show all the changes in that
- changeset, not just the files that contains the change
+ changeset, not just the files that contain the change
in <string>.
-O<orderfile>::
diff --git a/Documentation/diffcore.txt b/Documentation/diffcore.txt
--- a/Documentation/diffcore.txt
+++ b/Documentation/diffcore.txt
@@ -177,7 +177,7 @@ diffcore-merge-broken
---------------------
This transformation is used to merge filepairs broken by
-diffcore-break, and were not transformed into rename/copy by
+diffcore-break, and not transformed into rename/copy by
diffcore-rename, back into a single modification. This always
runs when diffcore-break is used.
@@ -206,10 +206,10 @@ like these:
* -B/60 (the same as above, since diffcore-break defaults to 50%).
Note that earlier implementation left a broken pair as a separate
-creation and deletion patches. This was unnecessary hack and
+creation and deletion patches. This was an unnecessary hack and
the latest implementation always merges all the broken pairs
back into modifications, but the resulting patch output is
-formatted differently to still let the reviewing easier for such
+formatted differently for easier review in case of such
a complete rewrite by showing the entire contents of old version
prefixed with '-', followed by the entire contents of new
version prefixed with '+'.
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -11,7 +11,7 @@ SYNOPSIS
DESCRIPTION
-----------
-A simple wrapper to git-update-index to add files to the cache for people used
+A simple wrapper for git-update-index to add files to the cache for people used
to do "cvs add".
OPTIONS
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -13,7 +13,7 @@ SYNOPSIS
DESCRIPTION
-----------
-Reads supplied diff output and applies it on a GIT index file
+Reads supplied diff output and applies it on a git index file
and a work tree.
OPTIONS
diff --git a/Documentation/git-applymbox.txt b/Documentation/git-applymbox.txt
--- a/Documentation/git-applymbox.txt
+++ b/Documentation/git-applymbox.txt
@@ -22,7 +22,7 @@ OPTIONS
-q::
Apply patches interactively. The user will be given
opportunity to edit the log message and the patch before
- attempting to apply patch in each e-mail message.
+ attempting to apply it.
-k::
Usually the program 'cleans up' the Subject: header line
diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.txt
--- a/Documentation/git-archimport.txt
+++ b/Documentation/git-archimport.txt
@@ -20,20 +20,23 @@ it will just import it as a regular comm
as a merge whenever possible (see discussion below).
The script expects you to provide the key roots where it can start the import
-from an 'initial import' or 'tag' type of Arch commit. It will follow and import
-new branches within the provided roots.
+from an 'initial import' or 'tag' type of Arch commit. It will follow and
+import new branches within the provided roots.
It expects to be dealing with one project only. If it sees
-branches that have different roots, it will refuse to run. In that case, edit your
-<archive/branch> parameters to define clearly the scope of the import.
+branches that have different roots, it will refuse to run. In that case,
+edit your <archive/branch> parameters to define clearly the scope of the
+import.
-`git-archimport` uses `tla` extensively in the background to access the Arch repository.
+`git-archimport` uses `tla` extensively in the background to access the
+Arch repository.
Make sure you have a recent version of `tla` available in the path. `tla` must
know about the repositories you pass to `git-archimport`.
For the initial import `git-archimport` expects to find itself in an empty
directory. To follow the development of a project that uses Arch, rerun
-`git-archimport` with the same parameters as the initial import to perform incremental imports.
+`git-archimport` with the same parameters as the initial import to perform
+incremental imports.
MERGES
------
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -76,7 +76,7 @@ During the bisection process, you can sa
to see the currently remaining suspects in `gitk`.
-The good/bad you told the command is logged, and `git bisect
+The good/bad input is logged, and `git bisect
log` shows what you have done so far. You can truncate its
output somewhere and save it in a file, and run
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -23,7 +23,7 @@ OPTIONS
The name of the branch to create.
start-point::
- Where to make the branch; defaults to HEAD.
+ Where to create the branch; defaults to HEAD.
Author
------
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -32,7 +32,7 @@ OPTIONS
<type>::
Typically this matches the real type of <object> but asking
- for a type that can trivially dereferenced from the given
+ for a type that can trivially be dereferenced from the given
<object> is also permitted. An example is to ask for a
"tree" with <object> being a commit object that contains it,
or to ask for a "blob" with <object> being a tag object that
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -22,7 +22,7 @@ OPTIONS
Commit to cherry-pick.
-r::
- Usuall the command appends which commit was
+ Usually the command appends which commit was
cherry-picked after the original commit message when
making a commit. This option, '--replay', causes it to
use the original commit message intact. This is useful
diff --git a/Documentation/git-clone-pack.txt b/Documentation/git-clone-pack.txt
--- a/Documentation/git-clone-pack.txt
+++ b/Documentation/git-clone-pack.txt
@@ -26,8 +26,8 @@ OPTIONS
--exec=<git-upload-pack>::
Use this to specify the path to 'git-upload-pack' on the
- remote side, if is not found on your $PATH.
- Installations of sshd ignores the user's environment
+ remote side, if it is not found on your $PATH.
+ Installations of sshd ignore the user's environment
setup scripts for login shells (e.g. .bash_profile) and
your privately installed GIT may not be found on the system
default $PATH. Another workaround suggested is to set
diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt
--- a/Documentation/git-commit-tree.txt
+++ b/Documentation/git-commit-tree.txt
@@ -36,7 +36,7 @@ OPTIONS
An existing tree object
-p <parent commit>::
- Each '-p' indicates a the id of a parent commit object.
+ Each '-p' indicates the id of a parent commit object.
Commit Information
^ permalink raw reply
* [PATCH] Add support for parallel HTTP transfers
From: Nick Hengeveld @ 2005-10-05 21:44 UTC (permalink / raw)
To: git
Add support for parallel HTTP transfers. Prefetch populates a queue of
objects to transfer and starts feeding requests to an active request
queue for processing; fetch_object keeps the active queue moving
while the specified object is being transferred. The size of the active
queue can be restricted using -r and defaults to 5 concurrent transfers.
Signed-off-by: Nick Hengeveld <nickh@reactrix.com>
---
I could use extra eyes on this patch - it seems to be stable although I have
seen periodic cases during testing where it detects an empty server response
(from kernel.org?) Are there implications to downloading a (potentially large)
pack while objects contained in that pack have been prefetched and are in the
transfer and/or active queue?
http-fetch.c | 696 +++++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 494 insertions(+), 202 deletions(-)
fe069497b0f959d4f270e4f01000480dd50febb2
diff --git a/http-fetch.c b/http-fetch.c
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -6,6 +6,8 @@
#include <curl/curl.h>
#include <curl/easy.h>
+#define DEFAULT_MAX_REQUESTS 5
+
#if LIBCURL_VERSION_NUM < 0x070704
#define curl_global_cleanup() do { /* nothing */ } while(0)
#endif
@@ -16,13 +18,14 @@
#define PREV_BUF_SIZE 4096
#define RANGE_HEADER_SIZE 30
-static CURL *curl;
+static int max_requests = DEFAULT_MAX_REQUESTS;
+
+static CURLM *curlm;
+static CURL *curl_default;
static struct curl_slist *no_pragma_header;
static struct curl_slist *no_range_header;
static char curl_errorstr[CURL_ERROR_SIZE];
-static char *initial_base;
-
struct alt_base
{
char *base;
@@ -33,11 +36,43 @@ struct alt_base
static struct alt_base *alt = NULL;
-static SHA_CTX c;
-static z_stream stream;
+enum transfer_state {
+ WAITING,
+ ABORTED,
+ ACTIVE,
+ COMPLETE,
+};
+
+struct transfer_request
+{
+ unsigned char sha1[20];
+ struct alt_base *repo;
+ char *url;
+ char filename[PATH_MAX];
+ char tmpfile[PATH_MAX];
+ int local;
+ enum transfer_state state;
+ CURLcode curl_result;
+ char errorstr[CURL_ERROR_SIZE];
+ long http_code;
+ unsigned char real_sha1[20];
+ SHA_CTX c;
+ z_stream stream;
+ int zret;
+ int rename;
+ struct active_request_slot *slot;
+ struct transfer_request *next;
+};
+
+struct active_request_slot
+{
+ CURL *curl;
+ int in_use;
+ struct active_request_slot *next;
+};
-static int local;
-static int zret;
+static struct transfer_request *request_queue_head = NULL;
+static struct active_request_slot *active_queue_head = NULL;
static int curl_ssl_verify;
static char *ssl_cert;
@@ -69,28 +104,27 @@ static size_t fwrite_sha1_file(void *ptr
unsigned char expn[4096];
size_t size = eltsize * nmemb;
int posn = 0;
+ struct transfer_request *request = (struct transfer_request *)data;
do {
- ssize_t retval = write(local, ptr + posn, size - posn);
+ ssize_t retval = write(request->local,
+ ptr + posn, size - posn);
if (retval < 0)
return posn;
posn += retval;
} while (posn < size);
- stream.avail_in = size;
- stream.next_in = ptr;
+ request->stream.avail_in = size;
+ request->stream.next_in = ptr;
do {
- stream.next_out = expn;
- stream.avail_out = sizeof(expn);
- zret = inflate(&stream, Z_SYNC_FLUSH);
- SHA1_Update(&c, expn, sizeof(expn) - stream.avail_out);
- } while (stream.avail_in && zret == Z_OK);
+ request->stream.next_out = expn;
+ request->stream.avail_out = sizeof(expn);
+ request->zret = inflate(&request->stream, Z_SYNC_FLUSH);
+ SHA1_Update(&request->c, expn,
+ sizeof(expn) - request->stream.avail_out);
+ } while (request->stream.avail_in && request->zret == Z_OK);
return size;
}
-void prefetch(unsigned char *sha1)
-{
-}
-
int relink_or_rename(char *old, char *new) {
int ret;
@@ -110,10 +144,296 @@ int relink_or_rename(char *old, char *ne
return 0;
}
+struct active_request_slot *get_active_slot()
+{
+ struct active_request_slot *slot = active_queue_head;
+ struct active_request_slot *newslot;
+
+ while (slot != NULL && slot->in_use) {
+ slot = slot->next;
+ }
+ if (slot == NULL) {
+ newslot = xmalloc(sizeof(*newslot));
+ newslot->curl = curl_easy_duphandle(curl_default);
+ newslot->in_use = 0;
+ newslot->next = NULL;
+
+ slot = active_queue_head;
+ if (slot == NULL) {
+ active_queue_head = newslot;
+ } else {
+ while (slot->next != NULL) {
+ slot = slot->next;
+ }
+ slot->next = newslot;
+ }
+ slot = newslot;
+ }
+
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_range_header);
+ curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
+
+ return slot;
+}
+
+void finish_request(struct transfer_request *request)
+{
+ fchmod(request->local, 0444);
+ close(request->local);
+
+ if (request->http_code == 416) {
+ fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
+ } else if (request->curl_result != CURLE_OK) {
+ return;
+ }
+
+ inflateEnd(&request->stream);
+ SHA1_Final(request->real_sha1, &request->c);
+ if (request->zret != Z_STREAM_END) {
+ unlink(request->tmpfile);
+ return;
+ }
+ if (memcmp(request->sha1, request->real_sha1, 20)) {
+ unlink(request->tmpfile);
+ return;
+ }
+ request->rename =
+ relink_or_rename(request->tmpfile, request->filename);
+}
+
+void release_request(struct transfer_request *request)
+{
+ struct transfer_request *entry = request_queue_head;
+
+ if (request == request_queue_head) {
+ request_queue_head = request->next;
+ } else {
+ while (entry->next != NULL && entry->next != request)
+ entry = entry->next;
+ if (entry->next == request)
+ entry->next = entry->next->next;
+ }
+
+ free(request->url);
+ free(request);
+}
+
+void start_request(struct transfer_request *request)
+{
+ char *hex = sha1_to_hex(request->sha1);
+ char prevfile[PATH_MAX];
+ char *url;
+ char *posn;
+ int prevlocal;
+ unsigned char prev_buf[PREV_BUF_SIZE];
+ ssize_t prev_read = 0;
+ long prev_posn = 0;
+ char range[RANGE_HEADER_SIZE];
+ struct curl_slist *range_header = NULL;
+ CURLMcode curlm_result;
+ struct active_request_slot *slot;
+
+ snprintf(prevfile, sizeof(prevfile), "%s.prev", request->filename);
+ unlink(prevfile);
+ rename(request->tmpfile, prevfile);
+ unlink(request->tmpfile);
+
+ request->local = open(request->tmpfile,
+ O_WRONLY | O_CREAT | O_EXCL, 0666);
+ if (request->local < 0) {
+ request->state = ABORTED;
+ error("Couldn't create temporary file %s for %s: %s\n",
+ request->tmpfile, request->filename, strerror(errno));
+ return;
+ }
+
+ memset(&request->stream, 0, sizeof(request->stream));
+
+ inflateInit(&request->stream);
+
+ SHA1_Init(&request->c);
+
+ url = xmalloc(strlen(request->repo->base) + 50);
+ request->url = xmalloc(strlen(request->repo->base) + 50);
+ strcpy(url, request->repo->base);
+ posn = url + strlen(request->repo->base);
+ strcpy(posn, "objects/");
+ posn += 8;
+ memcpy(posn, hex, 2);
+ posn += 2;
+ *(posn++) = '/';
+ strcpy(posn, hex + 2);
+ strcpy(request->url, url);
+
+ slot = get_active_slot();
+ slot->in_use = 1;
+ request->slot = slot;
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, request);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
+ curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+
+ /* If a previous temp file is present, process what was already
+ fetched. */
+ prevlocal = open(prevfile, O_RDONLY);
+ if (prevlocal != -1) {
+ do {
+ prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE);
+ if (prev_read>0) {
+ if (fwrite_sha1_file(prev_buf,
+ 1,
+ prev_read,
+ request) == prev_read) {
+ prev_posn += prev_read;
+ } else {
+ prev_read = -1;
+ }
+ }
+ } while (prev_read > 0);
+ close(prevlocal);
+ }
+ unlink(prevfile);
+
+ /* Reset inflate/SHA1 if there was an error reading the previous temp
+ file; also rewind to the beginning of the local file. */
+ if (prev_read == -1) {
+ memset(&request->stream, 0, sizeof(request->stream));
+ inflateInit(&request->stream);
+ SHA1_Init(&request->c);
+ if (prev_posn>0) {
+ prev_posn = 0;
+ lseek(request->local, SEEK_SET, 0);
+ ftruncate(request->local, 0);
+ }
+ }
+
+ /* If we have successfully processed data from a previous fetch
+ attempt, only fetch the data we don't already have. */
+ if (prev_posn>0) {
+ if (get_verbosely)
+ fprintf(stderr,
+ "Resuming fetch of object %s at byte %ld\n",
+ hex, prev_posn);
+ sprintf(range, "Range: bytes=%ld-", prev_posn);
+ range_header = curl_slist_append(range_header, range);
+ curl_easy_setopt(slot->curl,
+ CURLOPT_HTTPHEADER, range_header);
+ }
+
+ /* Try to add to multi handle, abort the request on error */
+ curlm_result = curl_multi_add_handle(curlm, slot->curl);
+ if (curlm_result != CURLM_OK &&
+ curlm_result != CURLM_CALL_MULTI_PERFORM) {
+ request->state = ABORTED;
+ close(request->local);
+ free(request->url);
+ slot->in_use = 0;
+ return;
+ }
+
+ request->slot = slot;
+ request->state = ACTIVE;
+}
+
+void process_curl_messages()
+{
+ int num_messages;
+ struct transfer_request *request;
+ CURLMsg *curl_message = curl_multi_info_read(curlm, &num_messages);
+
+ while (curl_message != NULL) {
+ if (curl_message->msg == CURLMSG_DONE) {
+ request = request_queue_head;
+ while (request != NULL) {
+ if (request->slot != NULL &&
+ request->slot->curl ==
+ curl_message->easy_handle)
+ break;
+ request = request->next;
+ }
+ if (request != NULL) {
+ curl_multi_remove_handle(curlm,
+ request->slot->curl);
+ request->curl_result =
+ curl_message->data.result;
+ curl_easy_getinfo(request->slot->curl,
+ CURLINFO_HTTP_CODE,
+ &request->http_code);
+ request->slot->in_use = 0;
+ request->slot = NULL;
+
+ /* Use alternates if necessary */
+ if (request->http_code == 404 &&
+ request->repo->next != NULL) {
+ request->repo = request->repo->next;
+ start_request(request);
+ } else {
+ finish_request(request);
+ request->state = COMPLETE;
+ }
+ } else {
+ fprintf(stderr, "Received DONE message for unknown request!\n");
+ }
+ } else {
+ fprintf(stderr, "Unknown CURL message received: %d\n",
+ (int)curl_message->msg);
+ }
+ curl_message = curl_multi_info_read(curlm, &num_messages);
+ }
+}
+
+void process_request_queue()
+{
+ struct transfer_request *request = request_queue_head;
+ int num_transfers;
+
+ curl_multi_perform(curlm, &num_transfers);
+ while (num_transfers < max_requests && request != NULL) {
+ while (request != NULL && request->state != WAITING)
+ request = request->next;
+ if (request != NULL) {
+ start_request(request);
+ curl_multi_perform(curlm, &num_transfers);
+ }
+ }
+}
+
+void prefetch(unsigned char *sha1)
+{
+ struct transfer_request *newreq;
+ struct transfer_request *tail;
+ char *filename = sha1_file_name(sha1);
+
+ newreq = xmalloc(sizeof(*newreq));
+ memcpy(newreq->sha1, sha1, 20);
+ newreq->repo = alt;
+ newreq->url = NULL;
+ newreq->local = -1;
+ newreq->state = WAITING;
+ snprintf(newreq->filename, sizeof(newreq->filename), "%s", filename);
+ snprintf(newreq->tmpfile, sizeof(newreq->tmpfile),
+ "%s.temp", filename);
+ newreq->next = NULL;
+
+ if (request_queue_head == NULL) {
+ request_queue_head = newreq;
+ } else {
+ tail = request_queue_head;
+ while (tail->next != NULL) {
+ tail = tail->next;
+ }
+ tail->next = newreq;
+ }
+ process_request_queue();
+ process_curl_messages();
+}
+
static int got_alternates = 0;
static int fetch_index(struct alt_base *repo, unsigned char *sha1)
{
+ char *hex = sha1_to_hex(sha1);
char *filename;
char *url;
char tmpfile[PATH_MAX];
@@ -124,17 +444,16 @@ static int fetch_index(struct alt_base *
CURLcode curl_result;
FILE *indexfile;
+ struct active_request_slot *slot = get_active_slot();
if (has_pack_index(sha1))
return 0;
if (get_verbosely)
- fprintf(stderr, "Getting index for pack %s\n",
- sha1_to_hex(sha1));
+ fprintf(stderr, "Getting index for pack %s\n", hex);
url = xmalloc(strlen(repo->base) + 64);
- sprintf(url, "%s/objects/pack/pack-%s.idx",
- repo->base, sha1_to_hex(sha1));
+ sprintf(url, "%s/objects/pack/pack-%s.idx", repo->base, hex);
filename = sha1_pack_index_name(sha1);
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
@@ -143,11 +462,9 @@ static int fetch_index(struct alt_base *
return error("Unable to open local file %s for pack index",
filename);
- curl_easy_setopt(curl, CURLOPT_FILE, indexfile);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
- curl_easy_setopt(curl, CURLOPT_URL, url);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_pragma_header);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errorstr);
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
/* If there is data present from a previous transfer attempt,
resume where it left off */
@@ -156,17 +473,14 @@ static int fetch_index(struct alt_base *
if (get_verbosely)
fprintf(stderr,
"Resuming fetch of index for pack %s at byte %ld\n",
- sha1_to_hex(sha1), prev_posn);
+ hex, prev_posn);
sprintf(range, "Range: bytes=%ld-", prev_posn);
range_header = curl_slist_append(range_header, range);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, range_header);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
}
- /* Clear out the Range: header after performing the request, so
- other curl requests don't inherit inappropriate header data */
- curl_result = curl_easy_perform(curl);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_range_header);
- if (curl_result != 0) {
+ curl_result = curl_easy_perform(slot->curl);
+ if (curl_result != CURLE_OK) {
fclose(indexfile);
return error("Unable to get pack index %s\n%s", url,
curl_errorstr);
@@ -205,6 +519,9 @@ static int fetch_alternates(char *base)
char *data;
int i = 0;
int http_specific = 1;
+ struct alt_base *tail = alt;
+
+ struct active_request_slot *slot = get_active_slot();
if (got_alternates)
return 0;
data = xmalloc(4096);
@@ -218,20 +535,18 @@ static int fetch_alternates(char *base)
url = xmalloc(strlen(base) + 31);
sprintf(url, "%s/objects/info/http-alternates", base);
- curl_easy_setopt(curl, CURLOPT_FILE, &buffer);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
- curl_easy_setopt(curl, CURLOPT_URL, url);
-
- if (curl_easy_perform(curl) || !buffer.posn) {
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+ if (curl_easy_perform(slot->curl) || !buffer.posn) {
http_specific = 0;
sprintf(url, "%s/objects/info/alternates", base);
- curl_easy_setopt(curl, CURLOPT_FILE, &buffer);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
- curl_easy_setopt(curl, CURLOPT_URL, url);
-
- if (curl_easy_perform(curl)) {
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+ if (curl_easy_perform(slot->curl)) {
return 0;
}
}
@@ -283,11 +598,13 @@ static int fetch_alternates(char *base)
fprintf(stderr,
"Also look at %s\n", target);
newalt = xmalloc(sizeof(*newalt));
- newalt->next = alt;
+ newalt->next = NULL;
newalt->base = target;
newalt->got_indices = 0;
newalt->packs = NULL;
- alt = newalt;
+ while (tail->next != NULL)
+ tail = tail->next;
+ tail->next = newalt;
ret++;
}
}
@@ -306,6 +623,8 @@ static int fetch_indices(struct alt_base
char *data;
int i = 0;
+ struct active_request_slot *slot = get_active_slot();
+
if (repo->got_indices)
return 0;
@@ -320,13 +639,12 @@ static int fetch_indices(struct alt_base
url = xmalloc(strlen(repo->base) + 21);
sprintf(url, "%s/objects/info/packs", repo->base);
- curl_easy_setopt(curl, CURLOPT_FILE, &buffer);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
- curl_easy_setopt(curl, CURLOPT_URL, url);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errorstr);
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
- if (curl_easy_perform(curl))
+ if (curl_easy_perform(slot->curl))
return error("%s", curl_errorstr);
while (i < buffer.posn) {
@@ -366,6 +684,8 @@ static int fetch_pack(struct alt_base *r
struct curl_slist *range_header = NULL;
CURLcode curl_result;
+ struct active_request_slot *slot = get_active_slot();
+
if (fetch_indices(repo))
return -1;
target = find_sha1_pack(sha1, repo->packs);
@@ -390,11 +710,9 @@ static int fetch_pack(struct alt_base *r
return error("Unable to open local file %s for pack",
filename);
- curl_easy_setopt(curl, CURLOPT_FILE, packfile);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
- curl_easy_setopt(curl, CURLOPT_URL, url);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_pragma_header);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errorstr);
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, packfile);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
/* If there is data present from a previous transfer attempt,
resume where it left off */
@@ -406,14 +724,11 @@ static int fetch_pack(struct alt_base *r
sha1_to_hex(target->sha1), prev_posn);
sprintf(range, "Range: bytes=%ld-", prev_posn);
range_header = curl_slist_append(range_header, range);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, range_header);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
}
- /* Clear out the Range: header after performing the request, so
- other curl requests don't inherit inappropriate header data */
- curl_result = curl_easy_perform(curl);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_range_header);
- if (curl_result != 0) {
+ curl_result = curl_easy_perform(slot->curl);
+ if (curl_result != CURLE_OK) {
fclose(packfile);
return error("Unable to get pack file %s\n%s", url,
curl_errorstr);
@@ -441,135 +756,92 @@ static int fetch_pack(struct alt_base *r
static int fetch_object(struct alt_base *repo, unsigned char *sha1)
{
char *hex = sha1_to_hex(sha1);
- char *filename = sha1_file_name(sha1);
- unsigned char real_sha1[20];
- char tmpfile[PATH_MAX];
- char prevfile[PATH_MAX];
int ret;
- char *url;
- char *posn;
- int prevlocal;
- unsigned char prev_buf[PREV_BUF_SIZE];
- ssize_t prev_read = 0;
- long prev_posn = 0;
- char range[RANGE_HEADER_SIZE];
- struct curl_slist *range_header = NULL;
- CURLcode curl_result;
-
- snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
- snprintf(prevfile, sizeof(prevfile), "%s.prev", filename);
-
- if (unlink(prevfile) && (errno != ENOENT))
- return error("Failed to unlink %s (%s)",
- prevfile, strerror(errno));
- if (rename(tmpfile, prevfile) && (errno != ENOENT))
- return error("Failed to rename %s to %s (%s)",
- tmpfile, prevfile, strerror(errno));
-
- local = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
-
- /* Note: if another instance starts now, it will turn our new
- tmpfile into its prevfile. */
-
- if (local < 0)
- return error("Couldn't create temporary file %s for %s: %s\n",
- tmpfile, filename, strerror(errno));
-
- memset(&stream, 0, sizeof(stream));
-
- inflateInit(&stream);
-
- SHA1_Init(&c);
+ struct transfer_request *request = request_queue_head;
+ int num_transfers;
+ int num_remaining;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set excfds;
+ int max_fd;
+ struct timeval select_timeout;
+ double download_size;
+ double current_size;
- curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
- curl_easy_setopt(curl, CURLOPT_FILE, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_pragma_header);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errorstr);
-
- url = xmalloc(strlen(repo->base) + 50);
- strcpy(url, repo->base);
- posn = url + strlen(repo->base);
- strcpy(posn, "objects/");
- posn += 8;
- memcpy(posn, hex, 2);
- posn += 2;
- *(posn++) = '/';
- strcpy(posn, hex + 2);
-
- curl_easy_setopt(curl, CURLOPT_URL, url);
+ while (request != NULL && memcmp(request->sha1, sha1, 20)) {
+ request = request->next;
+ }
+ if (request == NULL)
+ return error("Couldn't find request for %s in the queue", hex);
- /* If a previous temp file is present, process what was already
- fetched. */
- prevlocal = open(prevfile, O_RDONLY);
- if (prevlocal != -1) {
+ do {
+ do {} while (curl_multi_perform(curlm, &num_transfers) ==
+ CURLM_CALL_MULTI_PERFORM);
+ process_curl_messages();
+ process_request_queue();
+ } while (request->state == WAITING);
+
+ while (request->state == ACTIVE) {
+ curl_easy_getinfo(request->slot->curl,
+ CURLINFO_SIZE_DOWNLOAD,
+ &download_size);
do {
- prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE);
- if (prev_read>0) {
- if (fwrite_sha1_file(prev_buf,
- 1,
- prev_read,
- NULL) == prev_read) {
- prev_posn += prev_read;
- } else {
- prev_read = -1;
- }
+ num_remaining = num_transfers;
+ current_size = download_size;
+ curl_multi_perform(curlm, &num_transfers);
+ curl_easy_getinfo(request->slot->curl,
+ CURLINFO_SIZE_DOWNLOAD,
+ &download_size);
+ if (num_remaining != num_transfers) {
+ process_curl_messages();
+ process_request_queue();
}
- } while (prev_read > 0);
- close(prevlocal);
- }
- unlink(prevfile);
+ } while (download_size > current_size &&
+ request->state == ACTIVE);
- /* Reset inflate/SHA1 if there was an error reading the previous temp
- file; also rewind to the beginning of the local file. */
- if (prev_read == -1) {
- memset(&stream, 0, sizeof(stream));
- inflateInit(&stream);
- SHA1_Init(&c);
- if (prev_posn>0) {
- prev_posn = 0;
- lseek(local, SEEK_SET, 0);
- ftruncate(local, 0);
+ if (request->state == ACTIVE) {
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&excfds);
+ max_fd = 0;
+ select_timeout.tv_sec = 0;
+ select_timeout.tv_usec = 50000;
+ select(max_fd, &readfds, &writefds,
+ &excfds, &select_timeout);
}
}
- /* If we have successfully processed data from a previous fetch
- attempt, only fetch the data we don't already have. */
- if (prev_posn>0) {
- if (get_verbosely)
- fprintf(stderr,
- "Resuming fetch of object %s at byte %ld\n",
- hex, prev_posn);
- sprintf(range, "Range: bytes=%ld-", prev_posn);
- range_header = curl_slist_append(range_header, range);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, range_header);
+ if (request->state == ABORTED) {
+ release_request(request);
+ return error("Request for %s aborted", hex);
}
- /* Clear out the Range: header after performing the request, so
- other curl requests don't inherit inappropriate header data */
- curl_result = curl_easy_perform(curl);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_range_header);
- if (curl_result != 0) {
- return error("%s", curl_errorstr);
+ if (request->curl_result != CURLE_OK && request->http_code != 416) {
+ ret = error("%s", request->errorstr);
+ release_request(request);
+ return ret;
}
- fchmod(local, 0444);
- close(local);
- inflateEnd(&stream);
- SHA1_Final(real_sha1, &c);
- if (zret != Z_STREAM_END) {
- unlink(tmpfile);
- return error("File %s (%s) corrupt\n", hex, url);
+ if (request->zret != Z_STREAM_END) {
+ ret = error("File %s (%s) corrupt\n", hex, request->url);
+ release_request(request);
+ return ret;
}
- if (memcmp(sha1, real_sha1, 20)) {
- unlink(tmpfile);
+
+ if (memcmp(request->sha1, request->real_sha1, 20)) {
+ release_request(request);
return error("File %s has bad hash\n", hex);
}
- ret = relink_or_rename(tmpfile, filename);
- if (ret)
- return error("unable to write sha1 filename %s: %s",
- filename, strerror(ret));
+ if (request->rename < 0) {
+ ret = error("unable to write sha1 filename %s: %s",
+ request->filename,
+ strerror(request->rename));
+ release_request(request);
+ return ret;
+ }
+
+ release_request(request);
pull_say("got %s\n", hex);
return 0;
}
@@ -577,19 +849,16 @@ static int fetch_object(struct alt_base
int fetch(unsigned char *sha1)
{
struct alt_base *altbase = alt;
+
+ if (!fetch_object(altbase, sha1))
+ return 0;
while (altbase) {
- if (!fetch_object(altbase, sha1))
- return 0;
if (!fetch_pack(altbase, sha1))
return 0;
- if (fetch_alternates(altbase->base) > 0) {
- altbase = alt;
- continue;
- }
altbase = altbase->next;
}
return error("Unable to find %s under %s\n", sha1_to_hex(sha1),
- initial_base);
+ alt->base);
}
int fetch_ref(char *ref, unsigned char *sha1)
@@ -597,16 +866,16 @@ int fetch_ref(char *ref, unsigned char *
char *url, *posn;
char hex[42];
struct buffer buffer;
- char *base = initial_base;
+ char *base = alt->base;
+ struct active_request_slot *slot = get_active_slot();
buffer.size = 41;
buffer.posn = 0;
buffer.buffer = hex;
hex[41] = '\0';
- curl_easy_setopt(curl, CURLOPT_FILE, &buffer);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errorstr);
+ curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
+ curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
url = xmalloc(strlen(base) + 6 + strlen(ref));
strcpy(url, base);
@@ -615,9 +884,9 @@ int fetch_ref(char *ref, unsigned char *
posn += 5;
strcpy(posn, ref);
- curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(slot->curl, CURLOPT_URL, url);
- if (curl_easy_perform(curl))
+ if (curl_easy_perform(slot->curl))
return error("Couldn't get %s for %s\n%s",
url, ref, curl_errorstr);
@@ -631,6 +900,7 @@ int main(int argc, char **argv)
char *commit_id;
char *url;
int arg = 1;
+ struct active_request_slot *slot;
while (arg < argc && argv[arg][0] == '-') {
if (argv[arg][1] == 't') {
@@ -648,6 +918,11 @@ int main(int argc, char **argv)
arg++;
} else if (!strcmp(argv[arg], "--recover")) {
get_recover = 1;
+ } else if (argv[arg][1] == 'r') {
+ max_requests = atoi(argv[arg + 1]);
+ if (max_requests < 1)
+ max_requests = DEFAULT_MAX_REQUESTS;
+ arg++;
}
arg++;
}
@@ -660,44 +935,61 @@ int main(int argc, char **argv)
curl_global_init(CURL_GLOBAL_ALL);
- curl = curl_easy_init();
+ curlm = curl_multi_init();
+ if (curlm == NULL)
+ fprintf(stderr, "Error creating curl multi handle.\n");
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
no_range_header = curl_slist_append(no_range_header, "Range:");
curl_ssl_verify = getenv("GIT_SSL_NO_VERIFY") ? 0 : 1;
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
+ ssl_cert = getenv("GIT_SSL_CERT");
+ ssl_key = getenv("GIT_SSL_KEY");
+ ssl_capath = getenv("GIT_SSL_CAPATH");
+ ssl_cainfo = getenv("GIT_SSL_CAINFO");
+
+ curl_default = curl_easy_init();
+ curl_easy_setopt(curl_default, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
#if LIBCURL_VERSION_NUM >= 0x070907
- curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+ curl_easy_setopt(curl_default, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
#endif
- if ((ssl_cert = getenv("GIT_SSL_CERT")) != NULL) {
- curl_easy_setopt(curl, CURLOPT_SSLCERT, ssl_cert);
+ if (ssl_cert != NULL) {
+ curl_easy_setopt(curl_default, CURLOPT_SSLCERT, ssl_cert);
}
#if LIBCURL_VERSION_NUM >= 0x070902
- if ((ssl_key = getenv("GIT_SSL_KEY")) != NULL) {
- curl_easy_setopt(curl, CURLOPT_SSLKEY, ssl_key);
+ if (ssl_key != NULL) {
+ curl_easy_setopt(curl_default, CURLOPT_SSLKEY, ssl_key);
}
#endif
#if LIBCURL_VERSION_NUM >= 0x070908
- if ((ssl_capath = getenv("GIT_SSL_CAPATH")) != NULL) {
- curl_easy_setopt(curl, CURLOPT_CAPATH, ssl_capath);
+ if (ssl_capath != NULL) {
+ curl_easy_setopt(curl_default, CURLOPT_CAPATH, ssl_capath);
}
#endif
- if ((ssl_cainfo = getenv("GIT_SSL_CAINFO")) != NULL) {
- curl_easy_setopt(curl, CURLOPT_CAINFO, ssl_cainfo);
+ if (ssl_cainfo != NULL) {
+ curl_easy_setopt(curl_default, CURLOPT_CAINFO, ssl_cainfo);
}
+ curl_easy_setopt(curl_default, CURLOPT_FAILONERROR, 1);
alt = xmalloc(sizeof(*alt));
alt->base = url;
alt->got_indices = 0;
alt->packs = NULL;
alt->next = NULL;
- initial_base = url;
+ fetch_alternates(alt->base);
if (pull(commit_id))
return 1;
curl_slist_free_all(no_pragma_header);
+ curl_slist_free_all(no_range_header);
+ curl_easy_cleanup(curl_default);
+ slot = active_queue_head;
+ while (slot != NULL) {
+ curl_easy_cleanup(slot->curl);
+ slot = slot->next;
+ }
+ curl_multi_cleanup(curlm);
curl_global_cleanup();
return 0;
}
^ permalink raw reply
* Re: clone: I'm only doing a max of 256 requests
From: Junio C Hamano @ 2005-10-05 21:38 UTC (permalink / raw)
To: git; +Cc: linux-kernel
In-Reply-To: <7vhdbvk6ln.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> 1. As a stop gap measure, so that your Linux kernel work can
> continue, please bump MAX_NEEDS definition in upload-pack.c
> from 256 to a bit higher. That controls the number of
> 40-letter SHA1 given to underlying rev-list via execvp(), so
> it cannot be _too_ big like 1M, lest it exceeds the exec
> argument buffer limit.
Hmph. I was reading linux-2.6/fs/exec.c::copy_strings(), but I
do not see any such size limit (other than exceeding the total
machine memory size, probably reported by alloc_page() failing)
imposed there. Am I looking at the wrong place?
^ permalink raw reply
* Re: [PATCH] Enable and fix support for base less merges.
From: Junio C Hamano @ 2005-10-05 21:22 UTC (permalink / raw)
To: Fredrik Kuivinen; +Cc: git
In-Reply-To: <20051005203230.GB1833@c165.ib.student.liu.se>
Fredrik Kuivinen <freku045@student.liu.se> writes:
> Anyway, the idea I have thought about is to use (probably
> base64-encoded) xdelta diffs for the binary files. With this approach
> git diffs could look like:
>
> diff --git --xdelta a/foo b/foo
> <base64-encoded xdelta data>
>
> Is this approach reasonable?
If we continue to operate within 3-way merge paradigm of
"merging his changes to common ancestor into mine", more
appropriate would be to make the use of "merge" a bit more
configurable. As HPA mentioned, XML for example is a text file
not binary, but textual merge of it often produces less than
usable results, especially when it is machine generated, meant
to be consumed by machines, and optimized for compactness. Just
like we made merge strategy backends pluggable to git-merge,
strategy backends, after making their own decision on what 3
blobs to use for 3-way file-level merge, can be told which
low-level merge program to use (merge, diff3, wiggle, ...).
^ permalink raw reply
* Re: clone: I'm only doing a max of 256 requests
From: Junio C Hamano @ 2005-10-05 21:16 UTC (permalink / raw)
To: git
In-Reply-To: <7virwbu4wz.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> Andy Isaacson <adi@hexapodia.org> writes:
>
>> ... (And how should I be starting to
>> debug this? The git programs don't seem to have a useful --verbose
>> option. It would be nice if "git -v clone" would tell me what it is
>> doing.)
>
> $ git grep -n 'max of .* requests'
> upload-pack.c:141: die("I'm only doing a max of %d requests", MAX_NEEDS);
>
> I suspect that the repository you are cloning has too many
> branch heads and tags under .git/refs/.
We can do three things, the first two being short term, the last
one a bit longer term.
1. As a stop gap measure, so that your Linux kernel work can
continue, please bump MAX_NEEDS definition in upload-pack.c
from 256 to a bit higher. That controls the number of
40-letter SHA1 given to underlying rev-list via execvp(), so
it cannot be _too_ big like 1M, lest it exceeds the exec
argument buffer limit.
2. We can add '--all' flag to git-rev-list, and have upload-pack
use it instead, when it sees more than MAX_NEEDS refs. I
have a patch to do this that I am currently testing.
3. In addition, upload-pack should probably be taught to detect
"I do not have anything. Please give me objects reachable
from all your refs" requests, and cache the resulting pack
somewhere (invalidate whenever any ref changes), so that next
'clone' request can just send it out instead of rerunning
rev-list and pack-objects.
^ permalink raw reply
* Re: [PATCH] Enable and fix support for base less merges.
From: Fredrik Kuivinen @ 2005-10-05 20:32 UTC (permalink / raw)
To: Martin Langhoff; +Cc: Fredrik Kuivinen, git
In-Reply-To: <46a038f90510032322t6623c8d4y969e4e00bf4dfe26@mail.gmail.com>
On Tue, Oct 04, 2005 at 07:22:04PM +1300, Martin Langhoff wrote:
> On 10/4/05, Fredrik Kuivinen <freku045@student.liu.se> wrote:
> > I don't really understand what you mean. In what way could git-apply
> > use this? Is there a specific use case you are thinking about?
>
> Hmmm, perhaps I'm not understanding what a 'base less' merge is.
>
A base less merge is a merge of two branches which do not have a
common ancestor. That is, git-merge-base --all branch-A branch-B will
not return any results.
> Lately, I've been doing some "merges" where there was no common
> ancestor (known to git) and doing some lightweight cherrypicking by
> using `git-format-patch --mbox -o tmpdir` and then using
> git-applymbox. This is very useful to "replay" history against a
> different git repo (or branch) that doesn't share a common ancestor.
>
> But this has no support from the new smart merging mechanisms, which
> could potentially help by applying a patch to a renamed file. I'm not
> sure whether the "recursive" strategy needs 2 parents to figure this
> out, but if it doesn't, this'd be interesting to have. But at the time
> git-apply is cold, limited and unhelpful.
A base less merge is handled exactly as if there was a common ancestor
for the two branches with an empty tree. Renames are detected by
executing git-diff-tree -M --diff-filter=R -r <common ancestor>
<branch-A> and the analogous command for <branch-B>. Hence, if <common
ancestor> corresponds to an empty tree no renames will be detected.
I guess the major difference between cherrypicking with
git-format-patch and merging is that a merge is pretty much an all or
nothing thing. If you merge a branch you will get every commit from
that branch (and if you don't merge you will obviously not get any
commits at all).
> If baseless merges support what I am doing without resorting to
> patches, I'd be a really happy camper. Using mbox patchruns sucks,
> thank you very much for asking, because they don't support binary
> files.
It's unfortunate that binary files aren't supported. I have been
thinking about doing something about it, there isn't any code yet
though.
Anyway, the idea I have thought about is to use (probably
base64-encoded) xdelta diffs for the binary files. With this approach
git diffs could look like:
diff --git --xdelta a/foo b/foo
<base64-encoded xdelta data>
Is this approach reasonable?
- Fredrik
^ permalink raw reply
* git-show-index rename suggestion?
From: Jon Loeliger @ 2005-10-05 20:31 UTC (permalink / raw)
To: Git List
So, I was reading up on the various "index" operations
like git-diff-index, git-checkout-index, etc. Things
that operated on the index.
Naturally, I was surprised when I realized "git-show-index"
has nothing to do with the index, but rather the .idx "index"
files associated with packs.
Um, git-show-pack-index?
Ducking,
jdl
^ permalink raw reply
* Re: First cut at git port to Cygwin
From: Christopher Faylor @ 2005-10-05 20:29 UTC (permalink / raw)
To: Git Mailing List
In-Reply-To: <20051005191741.GA25493@steel.home>
On Wed, Oct 05, 2005 at 09:17:41PM +0200, Alex Riesen wrote:
>Christopher Faylor, Wed, Oct 05, 2005 17:54:57 +0200:
>> >Still does not work for me. I cannot isolate the problem out of git,
>> >but at the moment the only way for me to make commit_index_file to work
>> >is to put unlink(indexfile) before rename(cf->lockfile, indexfile).
>> >
>> >For everyone interested, I attach cygwin's strace output here.
>>
>> I'm sorry that I missed this thread. I'm usually pretty alert to the word
>> "cygwin" showing up in a subject.
>>
>> I'll go back and read the archives to catch up but, at the risk of
>> making an observation that has already been made, under windows you
>> can't always rename a file that is open. Is that what's happening here?
>>
>
>Don't think so, but will check in about 10 hrs. The code in question
>is in index.c, commit_index_file.
Ok. Looks pretty simple. FWIW, I've just built git on windows and I
don't see this behavior. For the most part, it "just works".
I do see the gitk behavior but I'm tk illiterate too, unfortunately, so
I can't help there.
Cygwin's tcl/tk is a funny beast. It is primarily included (by me) to
allow for the operation of the insight debugger and is more windows than
POSIX. As was noted, it doesn't interact with Cygwin/X but just draws
windows using the Windows API.
So, tcl/tk are just barely supported in Cygwin currently. I'm actually
a little surprised that it works as well as it does with gitk.
--
Christopher Faylor spammer? -> aaaspam@sourceware.org
Cygwin Co-Project Leader aaaspam@duffek.com
TimeSys, Inc.
^ permalink raw reply
* Re: clone: I'm only doing a max of 256 requests
From: Junio C Hamano @ 2005-10-05 19:42 UTC (permalink / raw)
To: git
In-Reply-To: <20051005191300.GC17475@hexapodia.org>
Andy Isaacson <adi@hexapodia.org> writes:
> ... (And how should I be starting to
> debug this? The git programs don't seem to have a useful --verbose
> option. It would be nice if "git -v clone" would tell me what it is
> doing.)
$ git grep -n 'max of .* requests'
upload-pack.c:141: die("I'm only doing a max of %d requests", MAX_NEEDS);
I suspect that the repository you are cloning has too many
branch heads and tags under .git/refs/.
^ permalink raw reply
* Re: First cut at git port to Cygwin
From: Alex Riesen @ 2005-10-05 19:17 UTC (permalink / raw)
To: Christopher Faylor; +Cc: Git Mailing List
In-Reply-To: <20051005155457.GA30303@trixie.casa.cgf.cx>
Christopher Faylor, Wed, Oct 05, 2005 17:54:57 +0200:
> >Still does not work for me. I cannot isolate the problem out of git,
> >but at the moment the only way for me to make commit_index_file to work
> >is to put unlink(indexfile) before rename(cf->lockfile, indexfile).
> >
> >For everyone interested, I attach cygwin's strace output here.
>
> I'm sorry that I missed this thread. I'm usually pretty alert to the word
> "cygwin" showing up in a subject.
>
> I'll go back and read the archives to catch up but, at the risk of
> making an observation that has already been made, under windows you
> can't always rename a file that is open. Is that what's happening here?
>
Don't think so, but will check in about 10 hrs. The code in question
is in index.c, commit_index_file.
^ permalink raw reply
* clone: I'm only doing a max of 256 requests
From: Andy Isaacson @ 2005-10-05 19:13 UTC (permalink / raw)
To: git
Trying to do a local clone of the linux-mips.org git repo:
% git clone /home/adi/linux/git/lmo/linux foo
defaulting to local storage area
fatal: I'm only doing a max of 256 requests
% git -v
git version 0.99.8.GIT
I got git/lmo/linux from http://www.linux-mips.org/pub/scm/linux.git.
Am I doing something wrong, or what? (And how should I be starting to
debug this? The git programs don't seem to have a useful --verbose
option. It would be nice if "git -v clone" would tell me what it is
doing.)
-andy
^ permalink raw reply
* Re: [PATCH] hold_index_file_for_update should not unlink failed to open .lock files atexit
From: Junio C Hamano @ 2005-10-05 18:49 UTC (permalink / raw)
To: Alex Riesen; +Cc: git
In-Reply-To: <81b0412b0510050758v26b88f4o5f15e3ff01e9cd87@mail.gmail.com>
Thanks. Will apply.
^ permalink raw reply
* Re: First cut at git port to Cygwin
From: Davide Libenzi @ 2005-10-05 17:29 UTC (permalink / raw)
To: Christopher Faylor; +Cc: Git Mailing List
In-Reply-To: <20051005161546.GB30303@trixie.casa.cgf.cx>
On Wed, 5 Oct 2005, Christopher Faylor wrote:
> On Wed, Oct 05, 2005 at 09:09:49AM -0700, Davide Libenzi wrote:
>> On 10/5/05, Alex Riesen <raa.lkml@gmail.com> wrote:
>>> Still does not work for me. I cannot isolate the problem out of git,
>>> but at the moment the only way for me to make commit_index_file to work
>>> is to put unlink(indexfile) before rename(cf->lockfile, indexfile).
>>
>> I don't know how Cygwin implemented rename(), but if they used
>> MoveFile() they broke the POSIX rename() since MoveFile() fails if
>> destination already exists. They should have used
>> MoveFileEx(MOVEFILE_REPLACE_EXISTING) instead, to guarantee POSIX
>> semantics. The symptoms you're experiencing make me think this might
>> be the case (even if it is strange, since other Unix software would
>> fail the same way).
>
> Cygwin's rename is much more than just a simple wrapper around MoveFile
> or MoveFileEx. It tries hard to guarantee POSIX semantics within the
> strictures imposed by Windows.
Ouch, IC:
http://cygwin.com/cgi-bin/cvsweb.cgi/~checkout~/src/winsup/cygwin/syscalls.cc?rev=1.390&content-type=text/plain&cvsroot=src
That's quite some code.
- Davide
^ permalink raw reply
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