Merge branch 'fixes'

maint
Junio C Hamano 2005-10-05 16:57:23 -07:00
commit d67c4af41f
25 changed files with 140 additions and 83 deletions

View File

@ -7,6 +7,9 @@
# Show GIT link as: <command>(<section>); if section is defined, else just show # Show GIT link as: <command>(<section>); if section is defined, else just show
# the command. # the command.


[attributes]
caret=^

ifdef::backend-docbook[] ifdef::backend-docbook[]
[gitlink-inlinemacro] [gitlink-inlinemacro]
{0%{target}} {0%{target}}
@ -19,3 +22,5 @@ ifdef::backend-xhtml11[]
[gitlink-inlinemacro] [gitlink-inlinemacro]
<a href="{target}.html">{target}{0?({0})}</a> <a href="{target}.html">{target}{0?({0})}</a>
endif::backend-xhtml11[] endif::backend-xhtml11[]



View File

@ -24,7 +24,7 @@ The good news is that most people don't do that, and in fact most sane
people think it's a bug in CVS that makes it tag (and check in changes) 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 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 '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 First off: this is not a git tutorial. See
link:tutorial.html[Documentation/tutorial.txt] for how git link:tutorial.html[Documentation/tutorial.txt] for how git
@ -229,7 +229,7 @@ does rename or copy would not show in the output, and if the
"o-file.c", it would find the commit that changed the statement "o-file.c", it would find the commit that changed the statement
when it was in "o-file.c". 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 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 was created by copying o-file.c unless o-file.c was somehow
changed in the same commit. changed in the same commit.

View File

@ -1,8 +1,8 @@
The output format from "git-diff-index", "git-diff-tree" and The output format from "git-diff-index", "git-diff-tree" and
"git-diff-files" are very similar. "git-diff-files" are very similar.


These commands all compare two sets of things; what are These commands all compare two sets of things; what is
compared are different: compared differs:


git-diff-index <tree-ish>:: git-diff-index <tree-ish>::
compares the <tree-ish> and the files on the filesystem. 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. . path for "dst"; only exists for C or R.
. an LF or a NUL when '-z' option is used, to terminate the record. . 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. and it is out of sync with the cache.


Example: Example:
@ -91,7 +91,7 @@ For a path that is added, removed, or modified,
where: where:


<old|new>-file:: are files GIT_EXTERNAL_DIFF can use to read the <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>-hex:: are the 40-hexdigit SHA1 hashes,
<old|new>-mode:: are the octal representation of the file modes. <old|new>-mode:: are the octal representation of the file modes.


@ -121,12 +121,11 @@ The `a/` and `b/` filenames are the same unless rename/copy is
involved. Especially, even for a creation or a deletion, involved. Especially, even for a creation or a deletion,
`/dev/null` is _not_ used in place of `a/` or `b/` filenames. `/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 name of the source file of the rename/copy and the name of
the file that rename/copy produces, respectively. the file that rename/copy produces, respectively.


2. It is followed by extended header lines that are one or 2. It is followed by one or more extended header lines:
more of:


old mode <mode> old mode <mode>
new mode <mode> new mode <mode>

View File

@ -5,9 +5,8 @@
Synonym for "-p". Synonym for "-p".


-r:: -r::
Look recursively in subdirectories; this flag does not Look recursively in subdirectories; only used by "git-diff-tree";
mean anything to commands other than "git-diff-tree"; other diff commands always work recursively.
other diff commands always look at all the subdirectories.


-z:: -z::
\0 line termination on output \0 line termination on output
@ -28,26 +27,26 @@
Detect copies as well as renames. Detect copies as well as renames.


--find-copies-harder:: --find-copies-harder::
By default, -C option finds copies only if the original For performance reasons, by default, -C option finds copies only
file of the copy was modified in the same changeset for if the original file of the copy was modified in the same
performance reasons. This flag makes the command changeset. This flag makes the command
inspect unmodified files as candidates for the source of inspect unmodified files as candidates for the source of
copy. This is a very expensive operation for large copy. This is a very expensive operation for large
projects, so use it with caution. projects, so use it with caution.


-l<num>:: -l<num>::
-M and -C options require O(n^2) processing time where n -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 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. number.


-S<string>:: -S<string>::
Look for differences that contains the change in <string>. Look for differences that contain the change in <string>.


--pickaxe-all:: --pickaxe-all::
When -S finds a change, show all the changes in that 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>. in <string>.


-O<orderfile>:: -O<orderfile>::

View File

@ -177,7 +177,7 @@ diffcore-merge-broken
--------------------- ---------------------


This transformation is used to merge filepairs broken by 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 diffcore-rename, back into a single modification. This always
runs when diffcore-break is used. runs when diffcore-break is used.


@ -206,10 +206,10 @@ like these:
* -B/60 (the same as above, since diffcore-break defaults to 50%). * -B/60 (the same as above, since diffcore-break defaults to 50%).


Note that earlier implementation left a broken pair as a separate 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 the latest implementation always merges all the broken pairs
back into modifications, but the resulting patch output is 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 a complete rewrite by showing the entire contents of old version
prefixed with '-', followed by the entire contents of new prefixed with '-', followed by the entire contents of new
version prefixed with '+'. version prefixed with '+'.

View File

@ -11,7 +11,7 @@ SYNOPSIS


DESCRIPTION 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". to do "cvs add".


OPTIONS OPTIONS

View File

@ -13,7 +13,7 @@ SYNOPSIS


DESCRIPTION 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. and a work tree.


OPTIONS OPTIONS

View File

@ -22,7 +22,7 @@ OPTIONS
-q:: -q::
Apply patches interactively. The user will be given Apply patches interactively. The user will be given
opportunity to edit the log message and the patch before opportunity to edit the log message and the patch before
attempting to apply patch in each e-mail message. attempting to apply it.


-k:: -k::
Usually the program 'cleans up' the Subject: header line Usually the program 'cleans up' the Subject: header line

View File

@ -20,20 +20,23 @@ it will just import it as a regular commit. If it can find it, it will mark it
as a merge whenever possible (see discussion below). as a merge whenever possible (see discussion below).


The script expects you to provide the key roots where it can start the import 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 from an 'initial import' or 'tag' type of Arch commit. It will follow and
new branches within the provided roots. import new branches within the provided roots.


It expects to be dealing with one project only. If it sees 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 branches that have different roots, it will refuse to run. In that case,
<archive/branch> parameters to define clearly the scope of the import. 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 Make sure you have a recent version of `tla` available in the path. `tla` must
know about the repositories you pass to `git-archimport`. know about the repositories you pass to `git-archimport`.


For the initial import `git-archimport` expects to find itself in an empty 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 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 MERGES
------ ------

View File

@ -76,7 +76,7 @@ During the bisection process, you can say


to see the currently remaining suspects in `gitk`. 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 log` shows what you have done so far. You can truncate its
output somewhere and save it in a file, and run output somewhere and save it in a file, and run



View File

@ -23,7 +23,7 @@ OPTIONS
The name of the branch to create. The name of the branch to create.


start-point:: start-point::
Where to make the branch; defaults to HEAD. Where to create the branch; defaults to HEAD.


Author Author
------ ------

View File

@ -32,7 +32,7 @@ OPTIONS


<type>:: <type>::
Typically this matches the real type of <object> but asking 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 <object> is also permitted. An example is to ask for a
"tree" with <object> being a commit object that contains it, "tree" with <object> being a commit object that contains it,
or to ask for a "blob" with <object> being a tag object that or to ask for a "blob" with <object> being a tag object that

View File

@ -22,7 +22,7 @@ OPTIONS
Commit to cherry-pick. Commit to cherry-pick.


-r:: -r::
Usuall the command appends which commit was Usually the command appends which commit was
cherry-picked after the original commit message when cherry-picked after the original commit message when
making a commit. This option, '--replay', causes it to making a commit. This option, '--replay', causes it to
use the original commit message intact. This is useful use the original commit message intact. This is useful

View File

@ -26,8 +26,8 @@ OPTIONS


--exec=<git-upload-pack>:: --exec=<git-upload-pack>::
Use this to specify the path to 'git-upload-pack' on the Use this to specify the path to 'git-upload-pack' on the
remote side, if is not found on your $PATH. remote side, if it is not found on your $PATH.
Installations of sshd ignores the user's environment Installations of sshd ignore the user's environment
setup scripts for login shells (e.g. .bash_profile) and setup scripts for login shells (e.g. .bash_profile) and
your privately installed GIT may not be found on the system your privately installed GIT may not be found on the system
default $PATH. Another workaround suggested is to set default $PATH. Another workaround suggested is to set

View File

@ -36,7 +36,7 @@ OPTIONS
An existing tree object An existing tree object


-p <parent commit>:: -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 Commit Information

View File

@ -54,13 +54,13 @@ OPTIONS
`git-diff-\*`). `git-diff-\*`).


--not:: --not::
When showing object names, prefix them with '^' and When showing object names, prefix them with '{caret}' and
strip '^' prefix from the object names that already have strip '{caret}' prefix from the object names that already have
one. one.


--symbolic:: --symbolic::
Usually the object names are output in SHA1 form (with 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. 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 happen to have both heads/master and tags/master, you can
explicitly say 'heads/master' to tell GIT which one you mean. explicitly say 'heads/master' to tell GIT which one you mean.


* A suffix '^' to a revision parameter means the first parent of * A suffix '{caret}' to a revision parameter means the first parent of
that commit object. '^<n>' means the <n>th parent (i.e. that commit object. '{caret}<n>' means the <n>th parent (i.e.
'rev^' 'rev{caret}'
is equivalent to 'rev^1'). As a special rule, is equivalent to 'rev{caret}1'). As a special rule,
'rev^0' means the commit itself and is used when 'rev' is the '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. object name of a tag object that refers to a commit object.


* A suffix '~<n>' to a revision parameter means the commit * A suffix '~<n>' to a revision parameter means the commit
object that is the <n>th generation grand-parent of the named object that is the <n>th generation grand-parent of the named
commit object, following only the first parent. I.e. rev~3 is 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 which is passed to 'git-rev-list'. Two revision parameters
concatenated with '..' is a short-hand for writing a range 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 Author

View File

@ -51,6 +51,7 @@ static void write_refs(struct ref *ref)
struct ref *head = NULL, *head_ptr, *master_ref; struct ref *head = NULL, *head_ptr, *master_ref;
char *head_path; char *head_path;


/* Upload-pack must report HEAD first */
if (!strcmp(ref->name, "HEAD")) { if (!strcmp(ref->name, "HEAD")) {
head = ref; head = ref;
ref = ref->next; ref = ref->next;
@ -60,17 +61,21 @@ static void write_refs(struct ref *ref)
while (ref) { while (ref) {
if (is_master(ref)) if (is_master(ref))
master_ref = ref; master_ref = ref;
if (head && !memcmp(ref->old_sha1, head->old_sha1, 20)) { if (head &&
if (!head_ptr || ref == master_ref) !memcmp(ref->old_sha1, head->old_sha1, 20) &&
head_ptr = ref; !strncmp(ref->name, "refs/heads/",11) &&
} (!head_ptr || ref == master_ref))
head_ptr = ref;

write_one_ref(ref); write_one_ref(ref);
ref = ref->next; ref = ref->next;
} }
if (!head) if (!head) {
fprintf(stderr, "No HEAD in remote.\n");
return; return;
}


head_path = git_path("HEAD"); head_path = strdup(git_path("HEAD"));
if (!head_ptr) { if (!head_ptr) {
/* /*
* If we had a master ref, and it wasn't HEAD, we need to undo the * If we had a master ref, and it wasn't HEAD, we need to undo the
@ -82,6 +87,7 @@ static void write_refs(struct ref *ref)
unlink(head_path); unlink(head_path);
} }
write_one_ref(head); write_one_ref(head);
free(head_path);
return; return;
} }


@ -89,13 +95,15 @@ static void write_refs(struct ref *ref)
if (master_ref) if (master_ref)
return; return;


fprintf(stderr, "Setting HEAD to %s\n", head_ptr->name);

/* /*
* Uhhuh. Other end didn't have master. We start HEAD off with * Uhhuh. Other end didn't have master. We start HEAD off with
* the first branch with the same value. * the first branch with the same value.
*/ */
unlink(head_path); if (create_symref(head_path, head_ptr->name) < 0)
if (symlink(head_ptr->name, head_path) < 0)
die("unable to link HEAD to %s", head_ptr->name); die("unable to link HEAD to %s", head_ptr->name);
free(head_path);
} }


static int clone_pack(int fd[2], int nr_match, char **match) static int clone_pack(int fd[2], int nr_match, char **match)

2
diff.h
View File

@ -103,7 +103,7 @@ extern void diff_flush(struct diff_options*);
/* these are not diff-raw status letters proper, but used by /* these are not diff-raw status letters proper, but used by
* diffcore-filter insn to specify additional restrictions. * diffcore-filter insn to specify additional restrictions.
*/ */
#define DIFF_STATUS_FILTER_AON 'A' #define DIFF_STATUS_FILTER_AON '*'
#define DIFF_STATUS_FILTER_BROKEN 'B' #define DIFF_STATUS_FILTER_BROKEN 'B'


#endif /* DIFF_H */ #endif /* DIFF_H */

View File

@ -198,7 +198,7 @@ else
PARENTS="" PARENTS=""
fi fi
git-status >>.editmsg git-status >>.editmsg
if [ "$?" != "0" -a ! -f $GIT_DIR/MERGE_HEAD ] if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" ]
then then
rm -f .editmsg rm -f .editmsg
git-status git-status

View File

@ -49,7 +49,7 @@ rsync_slurped_objects=


if test "" = "$append" if test "" = "$append"
then then
: >$GIT_DIR/FETCH_HEAD : >"$GIT_DIR/FETCH_HEAD"
fi fi


append_fetch_head () { append_fetch_head () {
@ -86,11 +86,11 @@ append_fetch_head () {
if git-cat-file commit "$head_" >/dev/null 2>&1 if git-cat-file commit "$head_" >/dev/null 2>&1
then then
headc_=$(git-rev-parse --verify "$head_^0") || exit headc_=$(git-rev-parse --verify "$head_^0") || exit
echo "$headc_ $not_for_merge_ $note_" >>$GIT_DIR/FETCH_HEAD echo "$headc_ $not_for_merge_ $note_" >>"$GIT_DIR/FETCH_HEAD"
echo >&2 "* committish: $head_" echo >&2 "* committish: $head_"
echo >&2 " $note_" echo >&2 " $note_"
else else
echo "$head_ not-for-merge $note_" >>$GIT_DIR/FETCH_HEAD echo "$head_ not-for-merge $note_" >>"$GIT_DIR/FETCH_HEAD"
echo >&2 "* non-commit: $head_" echo >&2 "* non-commit: $head_"
echo >&2 " $note_" echo >&2 " $note_"
fi fi

10
index.c
View File

@ -22,14 +22,16 @@ static void remove_lock_file_on_signal(int signo)


int hold_index_file_for_update(struct cache_file *cf, const char *path) int hold_index_file_for_update(struct cache_file *cf, const char *path)
{ {
int fd;
sprintf(cf->lockfile, "%s.lock", path); sprintf(cf->lockfile, "%s.lock", path);
cf->next = cache_file_list; fd = open(cf->lockfile, O_RDWR | O_CREAT | O_EXCL, 0666);
cache_file_list = cf; if (fd >=0 && !cf->next) {
if (!cf->next) { cf->next = cache_file_list;
cache_file_list = cf;
signal(SIGINT, remove_lock_file_on_signal); signal(SIGINT, remove_lock_file_on_signal);
atexit(remove_lock_file); atexit(remove_lock_file);
} }
return open(cf->lockfile, O_RDWR | O_CREAT | O_EXCL, 0666); return fd;
} }


int commit_index_file(struct cache_file *cf) int commit_index_file(struct cache_file *cf)

2
refs.c
View File

@ -46,7 +46,7 @@ int validate_symref(const char *path)
len -= 4; len -= 4;
while (len && isspace(*buf)) while (len && isspace(*buf))
buf++, len--; buf++, len--;
if (len >= 5 && !memcmp("refs/", buffer, 5)) if (len >= 5 && !memcmp("refs/", buf, 5))
return 0; return 0;
return -1; return -1;
} }

View File

@ -1,4 +1,5 @@
#include "cache.h" #include "cache.h"
#include "refs.h"
#include "tag.h" #include "tag.h"
#include "commit.h" #include "commit.h"
#include "tree.h" #include "tree.h"
@ -489,6 +490,22 @@ static void handle_one_commit(struct commit *com, struct commit_list **lst)
commit_list_insert(com, lst); 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) int main(int argc, char **argv)
{ {
@ -542,6 +559,10 @@ int main(int argc, char **argv)
bisect_list = 1; bisect_list = 1;
continue; continue;
} }
if (!strcmp(arg, "--all")) {
handle_all(&list);
continue;
}
if (!strcmp(arg, "--objects")) { if (!strcmp(arg, "--objects")) {
tag_objects = 1; tag_objects = 1;
tree_objects = 1; tree_objects = 1;

View File

@ -32,6 +32,7 @@ static int revs_count = 0;
static int is_rev_argument(const char *arg) static int is_rev_argument(const char *arg)
{ {
static const char *rev_args[] = { static const char *rev_args[] = {
"--all",
"--bisect", "--bisect",
"--header", "--header",
"--max-age=", "--max-age=",

View File

@ -30,10 +30,18 @@ static void create_pack_file(void)


if (!pid) { if (!pid) {
int i; int i;
int args = nr_has + nr_needs + 5; int args;
char **argv = xmalloc(args * sizeof(char *)); char **argv;
char *buf = xmalloc(args * 45); char *buf;
char **p = argv; 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); dup2(fd[1], 1);
close(0); close(0);
@ -41,10 +49,14 @@ static void create_pack_file(void)
close(fd[1]); close(fd[1]);
*p++ = "git-rev-list"; *p++ = "git-rev-list";
*p++ = "--objects"; *p++ = "--objects";
for (i = 0; i < nr_needs; i++) { if (MAX_NEEDS <= nr_needs)
*p++ = buf; *p++ = "--all";
memcpy(buf, sha1_to_hex(needs_sha1[i]), 41); else {
buf += 41; 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++) { for (i = 0; i < nr_has; i++) {
*p++ = buf; *p++ = buf;
@ -129,18 +141,24 @@ static int receive_needs(void)


needs = 0; needs = 0;
for (;;) { for (;;) {
unsigned char dummy[20], *sha1_buf;
len = packet_read_line(0, line, sizeof(line)); len = packet_read_line(0, line, sizeof(line));
if (!len) if (!len)
return needs; return needs;


/* sha1_buf = dummy;
* This is purely theoretical right now: git-fetch-pack only if (needs == MAX_NEEDS) {
* ever asks for a single HEAD fprintf(stderr,
*/ "warning: supporting only a max of %d requests. "
if (needs >= MAX_NEEDS) "sending everything instead.\n",
die("I'm only doing a max of %d requests", MAX_NEEDS); 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); 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++; needs++;
} }
} }