From 31ec6abf887ec95642cbe82fe61076e975494ab0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 14 Dec 2005 21:25:22 -0800 Subject: clone-pack: make it usable for partial branch cloning. clone-pack had some logic to accept subset of remote refs from the command line and clone from there. However, it was never used in practice and its problems were not found out so far. This commit changes the command to output the object names of refs to the standard output instead of making a clone of the remote repository when explicit parameters are given; the output format is the same as fetch-pack. The traditional behaviour of cloning the whole repository by giving no explicit parameters stays the same. Signed-off-by: Junio C Hamano --- Documentation/git-clone-pack.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/git-clone-pack.txt b/Documentation/git-clone-pack.txt index cfc7b62f31..39906fc450 100644 --- a/Documentation/git-clone-pack.txt +++ b/Documentation/git-clone-pack.txt @@ -43,7 +43,11 @@ OPTIONS The heads to update. This is relative to $GIT_DIR (e.g. "HEAD", "refs/heads/master"). When unspecified, all heads are updated to match the remote repository. - ++ +Usually all the refs from existing repository are stored +under the same name in the new repository. Giving explicit + arguments instead writes the object names and refs to +the standard output, just like get-fetch-pack does. Author ------ -- cgit v1.3 From 8431c4eb0976b0558eaa1df475ce6de6b52ce484 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 14 Dec 2005 23:08:08 -0800 Subject: Documentation: tutorial At the beginning of tutorial, refer the reader to everyday if she has not done so yet. Signed-off-by: Junio C Hamano --- Documentation/tutorial.txt | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Documentation') diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index a61b824443..543afb84e5 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -27,6 +27,12 @@ SCM, you can skip them during your first pass. [NOTE] And those "too deep" descriptions are often marked as Note. +[NOTE] +If you are already familiar with another version control system, +like CVS, you may want to take a look at +link:everyday.html[Everyday GIT in 20 commands or so] first +before reading this. + Creating a git repository ------------------------- -- cgit v1.3 From 3ae854c3567dd10055fbe12b8bd91bd2d447f55f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 16 Dec 2005 18:23:33 -0800 Subject: Examples of resetting. Morten Welinder says examples of resetting is really about recovering from botched commit/pulls. I agree that pointers from commands that cause a reset to be needed in the first place would be very helpful. Also reset examples did not mention "pull/merge" cases. Signed-off-by: Junio C Hamano --- Documentation/git-commit.txt | 4 ++++ Documentation/git-merge.txt | 5 +++++ Documentation/git-pull.txt | 5 +++++ Documentation/git-reset.txt | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+) (limited to 'Documentation') diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index b92cf48315..8b91f221fe 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -66,6 +66,10 @@ OPTIONS Update specified paths in the index file before committing. +If you make a commit and then found a mistake immediately after +that, you can recover from it with gitlink:git-reset[1]. + + Author ------ Written by Linus Torvalds and diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 0cac563d40..4ce799b520 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -37,6 +37,11 @@ include::merge-options.txt[] include::merge-strategies.txt[] +If you tried a merge which resulted in a complex conflicts and +would want to start over, you can recover with +gitlink:git-reset[1]. + + HOW MERGE WORKS --------------- diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt index c65ca9a530..3a7d385225 100644 --- a/Documentation/git-pull.txt +++ b/Documentation/git-pull.txt @@ -104,6 +104,11 @@ merge the remote `origin` head into the current, local `master` branch. +If you tried a pull which resulted in a complex conflicts and +would want to start over, you can recover with +gitlink:git-reset[1]. + + SEE ALSO -------- gitlink:git-fetch[1], gitlink:git-merge[1] diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index 02048918bf..c6a269b7ef 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -111,6 +111,39 @@ remain there. changes still in the working tree. ------------ +Undo a merge or pull:: ++ +------------ +$ git pull <1> +Trying really trivial in-index merge... +fatal: Merge requires file-level merging +Nope. +... +Auto-merging nitfol +CONFLICT (content): Merge conflict in nitfol +Automatic merge failed/prevented; fix up by hand +$ git reset --hard <2> + +<1> try to update from the upstream resulted in a lot of +conflicts; you were not ready to spend a lot of time merging +right now, so you decide to do that later. +<2> "pull" has not made merge commit, so "git reset --hard" +which is a synonym for "git reset --hard HEAD" clears the mess +from the index file and the working tree. + +$ git pull . topic/branch <3> +Updating from 41223... to 13134... +Fast forward +$ git reset --hard ORIG_HEAD <4> + +<3> merge a topic branch into the current branch, which resulted +in a fast forward. +<4> but you decided that the topic branch is not ready for public +consumption yet. "pull" or "merge" always leaves the original +tip of the current branch in ORIG_HEAD, so resetting hard to it +brings your index file and the working tree back to that state, +and resets the tip of the branch to that commit. +------------ Author ------ -- cgit v1.3 From 68283999f8ae0e9286f8b7f199905b77d608cb80 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 15 Dec 2005 18:03:59 -0800 Subject: Forbid pattern maching characters in refnames. by marking '?', '*', and '[' as bad_ref_char(). Signed-off-by: Junio C Hamano --- Documentation/git-check-ref-format.txt | 8 +++++--- refs.c | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt index 636e9516b0..f7f84c644e 100644 --- a/Documentation/git-check-ref-format.txt +++ b/Documentation/git-check-ref-format.txt @@ -26,13 +26,15 @@ imposes the following rules on how refs are named: . It cannot have ASCII control character (i.e. bytes whose values are lower than \040, or \177 `DEL`), space, tilde `~`, - caret `{caret}`, or colon `:` anywhere; + caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`, + or open bracket `[` anywhere; . It cannot end with a slash `/`. These rules makes it easy for shell script based tools to parse -refnames, and also avoids ambiguities in certain refname -expressions (see gitlink:git-rev-parse[1]). Namely: +refnames, pathname expansion by the shell when a refname is used +unquoted (by mistake), and also avoids ambiguities in certain +refname expressions (see gitlink:git-rev-parse[1]). Namely: . double-dot `..` are often used as in `ref1..ref2`, and in some context this notation means `{caret}ref1 ref2` (i.e. not in diff --git a/refs.c b/refs.c index 69858e48cb..7a2c56e64b 100644 --- a/refs.c +++ b/refs.c @@ -313,7 +313,9 @@ int write_ref_sha1(const char *ref, int fd, const unsigned char *sha1) static inline int bad_ref_char(int ch) { return (((unsigned) ch) <= ' ' || - ch == '~' || ch == '^' || ch == ':'); + ch == '~' || ch == '^' || ch == ':' || + /* 2.13 Pattern Matching Notation */ + ch == '?' || ch == '*' || ch == '['); } int check_ref_format(const char *ref) -- cgit v1.3 From 80248b2e4888a05adcb903f53af84ee513d22245 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 17 Dec 2005 11:39:39 -0800 Subject: Documentation: HTTP needs update-server-info. Signed-off-by: Junio C Hamano --- Documentation/everyday.txt | 11 +++++++++++ Documentation/git-update-server-info.txt | 6 +++--- Documentation/tutorial.txt | 18 +++++++++++------- 3 files changed, 25 insertions(+), 10 deletions(-) (limited to 'Documentation') diff --git a/Documentation/everyday.txt b/Documentation/everyday.txt index d8d7a6441a..df1e287999 100644 --- a/Documentation/everyday.txt +++ b/Documentation/everyday.txt @@ -424,3 +424,14 @@ for branch policy control. david is the release manager and is the only person who can create and push version tags. ------------ + +HTTP server to support dumb protocol transfer.:: ++ +------------ +dev$ git update-server-info <1> +dev$ ftp user@isp.example.com <2> +ftp> cp -r .git /home/user/myproject.git + +<1> make sure your info/refs and objects/info/packs are up-to-date +<2> upload to public HTTP server hosted by your ISP. +------------ diff --git a/Documentation/git-update-server-info.txt b/Documentation/git-update-server-info.txt index 527fb303eb..88a03c7c5e 100644 --- a/Documentation/git-update-server-info.txt +++ b/Documentation/git-update-server-info.txt @@ -12,11 +12,11 @@ SYNOPSIS DESCRIPTION ----------- -A dumb server that does not do on-the-fly pack generations can +A dumb server that does not do on-the-fly pack generations must have some auxiliary information files in $GIT_DIR/info and $GIT_OBJECT_DIRECTORY/info directories to help clients discover -what references and packs the server has and make optimized -pull decisions. This command generates such auxiliary files. +what references and packs the server has. This command +generates such auxiliary files. OPTIONS diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index 543afb84e5..1683f0bc2d 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -1091,9 +1091,10 @@ lacks and transfers (close to) minimum set of objects. HTTP(S):: `http://remote.machine/path/to/repo.git/` + -HTTP and HTTPS transport are used only for downloading. They -first obtain the topmost commit object name from the remote site -by looking at `repo.git/info/refs` file, tries to obtain the +Downloader from http and https URL +first obtains the topmost commit object name from the remote site +by looking at the specified refname under `repo.git/refs/` directory, +and then tries to obtain the commit object by downloading from `repo.git/objects/xx/xxx\...` using the object name of that commit object. Then it reads the commit object to find out its parent commits and the associate @@ -1104,7 +1105,9 @@ sometimes also called 'commit walkers'. The 'commit walkers' are sometimes also called 'dumb transports', because they do not require any git aware smart server like git Native transport does. Any stock HTTP server -would suffice. +that does not even support directory index would suffice. But +you must prepare your repository with `git-update-server-info` +to help dumb transport downloaders. + There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload` programs, which are 'commit walkers'; they outlived their @@ -1517,12 +1520,13 @@ A recommended workflow for a "project lead" goes like this: 2. Prepare a public repository accessible to others. + If other people are pulling from your repository over dumb -transport protocols, you need to keep this repository 'dumb -transport friendly'. After `git init-db`, +transport protocols (HTTP), you need to keep this repository +'dumb transport friendly'. After `git init-db`, `$GIT_DIR/hooks/post-update` copied from the standard templates would contain a call to `git-update-server-info` but the `post-update` hook itself is disabled by default -- enable it -with `chmod +x post-update`. +with `chmod +x post-update`. This makes sure `git-update-server-info` +keeps the necessary files up-to-date. 3. Push into the public repository from your primary repository. -- cgit v1.3 From ad8972150887a8ed3dd4869fc9318cc2e48dd69f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 14 Dec 2005 22:17:38 -0800 Subject: fetch-pack: -k option to keep downloaded pack. Split out the functions that deal with the socketpair after finishing git protocol handshake to receive the packed data into a separate file, and use it in fetch-pack to keep/explode the received pack data. We earlier had something like that on clone-pack side once, but the list discussion resulted in the decision that it makes sense to always keep the pack for clone-pack, so unpacking option is not enabled on the clone-pack side, but we later still could do so easily if we wanted to with this change. Signed-off-by: Junio C Hamano --- Documentation/git-fetch-pack.txt | 7 +- Makefile | 1 + cache.h | 5 ++ clone-pack.c | 136 +------------------------------ fetch-clone.c | 172 +++++++++++++++++++++++++++++++++++++++ fetch-pack.c | 58 +++++-------- 6 files changed, 206 insertions(+), 173 deletions(-) create mode 100644 fetch-clone.c (limited to 'Documentation') diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index ea6faab059..b507e9b648 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository. SYNOPSIS -------- -git-fetch-pack [-q] [--exec=] [:] [...] +git-fetch-pack [-q] [-k] [--exec=] [:] [...] DESCRIPTION ----------- @@ -29,6 +29,11 @@ OPTIONS Pass '-q' flag to 'git-unpack-objects'; this makes the cloning process less verbose. +-k:: + Do not invoke 'git-unpack-objects' on received data, but + create a single packfile out of it instead, and store it + in the object database. + --exec=:: Use this to specify the path to 'git-upload-pack' on the remote side, if is not found on your $PATH. diff --git a/Makefile b/Makefile index d494ad4b1f..9fd2ed3d92 100644 --- a/Makefile +++ b/Makefile @@ -175,6 +175,7 @@ LIB_OBJS = \ quote.o read-cache.o refs.o run-command.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ + fetch-clone.o \ $(DIFF_OBJS) LIBS = $(LIB_FILE) diff --git a/cache.h b/cache.h index c78d8aea41..cb87becb3a 100644 --- a/cache.h +++ b/cache.h @@ -338,4 +338,9 @@ extern char git_default_name[MAX_GITNAME]; extern char git_commit_encoding[MAX_ENCODING_LENGTH]; extern int copy_fd(int ifd, int ofd); + +/* Finish off pack transfer receiving end */ +extern int receive_unpack_pack(int fd[2], const char *me, int quiet); +extern int receive_keep_pack(int fd[2], const char *me); + #endif /* CACHE_H */ diff --git a/clone-pack.c b/clone-pack.c index b5ce5d3111..03dbc2ead6 100644 --- a/clone-pack.c +++ b/clone-pack.c @@ -1,7 +1,6 @@ #include "cache.h" #include "refs.h" #include "pkt-line.h" -#include static const char clone_pack_usage[] = "git-clone-pack [--exec=] [:] []*"; @@ -112,139 +111,6 @@ static void write_refs(struct ref *ref) free(head_path); } -static int finish_pack(const char *pack_tmp_name) -{ - int pipe_fd[2]; - pid_t pid; - char idx[PATH_MAX]; - char final[PATH_MAX]; - char hash[41]; - unsigned char sha1[20]; - char *cp; - int err = 0; - - if (pipe(pipe_fd) < 0) - die("git-clone-pack: unable to set up pipe"); - - strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */ - cp = strrchr(idx, '/'); - memcpy(cp, "/pidx", 5); - - pid = fork(); - if (pid < 0) - die("git-clone-pack: unable to fork off git-index-pack"); - if (!pid) { - close(0); - dup2(pipe_fd[1], 1); - close(pipe_fd[0]); - close(pipe_fd[1]); - execlp("git-index-pack","git-index-pack", - "-o", idx, pack_tmp_name, NULL); - error("cannot exec git-index-pack <%s> <%s>", - idx, pack_tmp_name); - exit(1); - } - close(pipe_fd[1]); - if (read(pipe_fd[0], hash, 40) != 40) { - error("git-clone-pack: unable to read from git-index-pack"); - err = 1; - } - close(pipe_fd[0]); - - for (;;) { - int status, code; - int retval = waitpid(pid, &status, 0); - - if (retval < 0) { - if (errno == EINTR) - continue; - error("waitpid failed (%s)", strerror(retval)); - goto error_die; - } - if (WIFSIGNALED(status)) { - int sig = WTERMSIG(status); - error("git-index-pack died of signal %d", sig); - goto error_die; - } - if (!WIFEXITED(status)) { - error("git-index-pack died of unnatural causes %d", - status); - goto error_die; - } - code = WEXITSTATUS(status); - if (code) { - error("git-index-pack died with error code %d", code); - goto error_die; - } - if (err) - goto error_die; - break; - } - hash[40] = 0; - if (get_sha1_hex(hash, sha1)) { - error("git-index-pack reported nonsense '%s'", hash); - goto error_die; - } - /* Now we have pack in pack_tmp_name[], and - * idx in idx[]; rename them to their final names. - */ - snprintf(final, sizeof(final), - "%s/pack/pack-%s.pack", get_object_directory(), hash); - move_temp_to_file(pack_tmp_name, final); - chmod(final, 0444); - snprintf(final, sizeof(final), - "%s/pack/pack-%s.idx", get_object_directory(), hash); - move_temp_to_file(idx, final); - chmod(final, 0444); - return 0; - - error_die: - unlink(idx); - unlink(pack_tmp_name); - exit(1); -} - -static int clone_without_unpack(int fd[2]) -{ - char tmpfile[PATH_MAX]; - int ofd, ifd; - - ifd = fd[0]; - snprintf(tmpfile, sizeof(tmpfile), - "%s/pack/tmp-XXXXXX", get_object_directory()); - ofd = mkstemp(tmpfile); - if (ofd < 0) - return error("unable to create temporary file %s", tmpfile); - - while (1) { - char buf[8192]; - ssize_t sz, wsz, pos; - sz = read(ifd, buf, sizeof(buf)); - if (sz == 0) - break; - if (sz < 0) { - error("error reading pack (%s)", strerror(errno)); - close(ofd); - unlink(tmpfile); - return -1; - } - pos = 0; - while (pos < sz) { - wsz = write(ofd, buf + pos, sz - pos); - if (wsz < 0) { - error("error writing pack (%s)", - strerror(errno)); - close(ofd); - unlink(tmpfile); - return -1; - } - pos += wsz; - } - } - close(ofd); - return finish_pack(tmpfile); -} - static int clone_pack(int fd[2], int nr_match, char **match) { struct ref *refs; @@ -257,7 +123,7 @@ static int clone_pack(int fd[2], int nr_match, char **match) } clone_handshake(fd, refs); - status = clone_without_unpack(fd); + status = receive_keep_pack(fd, "git-clone-pack"); if (!status) { if (nr_match == 0) diff --git a/fetch-clone.c b/fetch-clone.c new file mode 100644 index 0000000000..2b2aa15ea7 --- /dev/null +++ b/fetch-clone.c @@ -0,0 +1,172 @@ +#include "cache.h" +#include + +static int finish_pack(const char *pack_tmp_name, const char *me) +{ + int pipe_fd[2]; + pid_t pid; + char idx[PATH_MAX]; + char final[PATH_MAX]; + char hash[41]; + unsigned char sha1[20]; + char *cp; + int err = 0; + + if (pipe(pipe_fd) < 0) + die("%s: unable to set up pipe", me); + + strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */ + cp = strrchr(idx, '/'); + memcpy(cp, "/pidx", 5); + + pid = fork(); + if (pid < 0) + die("git-clone-pack: unable to fork off git-index-pack"); + if (!pid) { + close(0); + dup2(pipe_fd[1], 1); + close(pipe_fd[0]); + close(pipe_fd[1]); + execlp("git-index-pack","git-index-pack", + "-o", idx, pack_tmp_name, NULL); + error("cannot exec git-index-pack <%s> <%s>", + idx, pack_tmp_name); + exit(1); + } + close(pipe_fd[1]); + if (read(pipe_fd[0], hash, 40) != 40) { + error("%s: unable to read from git-index-pack", me); + err = 1; + } + close(pipe_fd[0]); + + for (;;) { + int status, code; + int retval = waitpid(pid, &status, 0); + + if (retval < 0) { + if (errno == EINTR) + continue; + error("waitpid failed (%s)", strerror(retval)); + goto error_die; + } + if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); + error("git-index-pack died of signal %d", sig); + goto error_die; + } + if (!WIFEXITED(status)) { + error("git-index-pack died of unnatural causes %d", + status); + goto error_die; + } + code = WEXITSTATUS(status); + if (code) { + error("git-index-pack died with error code %d", code); + goto error_die; + } + if (err) + goto error_die; + break; + } + hash[40] = 0; + if (get_sha1_hex(hash, sha1)) { + error("git-index-pack reported nonsense '%s'", hash); + goto error_die; + } + /* Now we have pack in pack_tmp_name[], and + * idx in idx[]; rename them to their final names. + */ + snprintf(final, sizeof(final), + "%s/pack/pack-%s.pack", get_object_directory(), hash); + move_temp_to_file(pack_tmp_name, final); + chmod(final, 0444); + snprintf(final, sizeof(final), + "%s/pack/pack-%s.idx", get_object_directory(), hash); + move_temp_to_file(idx, final); + chmod(final, 0444); + return 0; + + error_die: + unlink(idx); + unlink(pack_tmp_name); + exit(1); +} + +int receive_unpack_pack(int fd[2], const char *me, int quiet) +{ + int status; + pid_t pid; + + pid = fork(); + if (pid < 0) + die("%s: unable to fork off git-unpack-objects", me); + if (!pid) { + dup2(fd[0], 0); + close(fd[0]); + close(fd[1]); + execlp("git-unpack-objects", "git-unpack-objects", + quiet ? "-q" : NULL, NULL); + die("git-unpack-objects exec failed"); + } + close(fd[0]); + close(fd[1]); + while (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR) + die("waiting for git-unpack-objects: %s", + strerror(errno)); + } + if (WIFEXITED(status)) { + int code = WEXITSTATUS(status); + if (code) + die("git-unpack-objects died with error code %d", + code); + return 0; + } + if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); + die("git-unpack-objects died of signal %d", sig); + } + die("git-unpack-objects died of unnatural causes %d", status); +} + +int receive_keep_pack(int fd[2], const char *me) +{ + char tmpfile[PATH_MAX]; + int ofd, ifd; + + ifd = fd[0]; + snprintf(tmpfile, sizeof(tmpfile), + "%s/pack/tmp-XXXXXX", get_object_directory()); + ofd = mkstemp(tmpfile); + if (ofd < 0) + return error("unable to create temporary file %s", tmpfile); + + while (1) { + char buf[8192]; + ssize_t sz, wsz, pos; + sz = read(ifd, buf, sizeof(buf)); + if (sz == 0) + break; + if (sz < 0) { + error("error reading pack (%s)", strerror(errno)); + close(ofd); + unlink(tmpfile); + return -1; + } + pos = 0; + while (pos < sz) { + wsz = write(ofd, buf + pos, sz - pos); + if (wsz < 0) { + error("error writing pack (%s)", + strerror(errno)); + close(ofd); + unlink(tmpfile); + return -1; + } + pos += wsz; + } + } + close(ofd); + return finish_pack(tmpfile, me); +} diff --git a/fetch-pack.c b/fetch-pack.c index 58ba2094dc..2528053fa8 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -3,13 +3,12 @@ #include "pkt-line.h" #include "commit.h" #include "tag.h" -#include -#include +static int keep_pack; static int quiet; static int verbose; static const char fetch_pack_usage[] = -"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory ..."; +"git-fetch-pack [-q] [-v] [-k] [--exec=upload-pack] [host:]directory ..."; static const char *exec = "git-upload-pack"; #define COMPLETE (1U << 0) @@ -363,7 +362,6 @@ static int fetch_pack(int fd[2], int nr_match, char **match) struct ref *ref; unsigned char sha1[20]; int status; - pid_t pid; get_remote_heads(fd[0], &ref, 0, NULL, 0); if (server_supports("multi_ack")) { @@ -381,40 +379,22 @@ static int fetch_pack(int fd[2], int nr_match, char **match) } if (find_common(fd, sha1, ref) < 0) fprintf(stderr, "warning: no common commits\n"); - pid = fork(); - if (pid < 0) - die("git-fetch-pack: unable to fork off git-unpack-objects"); - if (!pid) { - dup2(fd[0], 0); - close(fd[0]); - close(fd[1]); - execlp("git-unpack-objects", "git-unpack-objects", - quiet ? "-q" : NULL, NULL); - die("git-unpack-objects exec failed"); - } - close(fd[0]); - close(fd[1]); - while (waitpid(pid, &status, 0) < 0) { - if (errno != EINTR) - die("waiting for git-unpack-objects: %s", strerror(errno)); - } - if (WIFEXITED(status)) { - int code = WEXITSTATUS(status); - if (code) - die("git-unpack-objects died with error code %d", code); -all_done: - while (ref) { - printf("%s %s\n", - sha1_to_hex(ref->old_sha1), ref->name); - ref = ref->next; - } - return 0; - } - if (WIFSIGNALED(status)) { - int sig = WTERMSIG(status); - die("git-unpack-objects died of signal %d", sig); + + if (keep_pack) + status = receive_keep_pack(fd, "git-fetch-pack"); + else + status = receive_unpack_pack(fd, "git-fetch-pack", quiet); + + if (status) + die("git-fetch-pack: fetch failed."); + + all_done: + while (ref) { + printf("%s %s\n", + sha1_to_hex(ref->old_sha1), ref->name); + ref = ref->next; } - die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status); + return 0; } int main(int argc, char **argv) @@ -440,6 +420,10 @@ int main(int argc, char **argv) quiet = 1; continue; } + if (!strcmp("-k", arg)) { + keep_pack = 1; + continue; + } if (!strcmp("-v", arg)) { verbose = 1; continue; -- cgit v1.3 From d808111ebdb0b50709527612221eb2970ed6ece9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 18 Dec 2005 12:11:27 -0800 Subject: Documentation: typos and small fixes in "everyday". Signed-off-by: Junio C Hamano --- Documentation/everyday.txt | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'Documentation') diff --git a/Documentation/everyday.txt b/Documentation/everyday.txt index df1e287999..3ab9b916c2 100644 --- a/Documentation/everyday.txt +++ b/Documentation/everyday.txt @@ -211,10 +211,12 @@ $ git fetch --tags <8> <1> repeat as needed. <2> extract patches from your branch for e-mail submission. -<3> "pull" fetches from "origin" by default and merges. -<4> look at the changes since last time we checked, only in the +<3> "pull" fetches from "origin" by default and merges into the +current branch. +<4> immediately after pulling, look at the changes done upstream +since last time we checked, only in the area we are interested in. -<5> fetch from a specific branch from a specific repository and and merge. +<5> fetch from a specific branch from a specific repository and merge. <6> revert the pull. <7> garbage collect leftover objects from reverted pull. <8> from time to time, obtain official tags from the "origin" @@ -330,16 +332,18 @@ master, nor exposed as a part of a stable branch. <8> and bundle topic branches still cooking. <9> backport a critical fix. <10> create a signed tag. -<11> make sure I did not accidentally rewound master beyond what I +<11> make sure I did not accidentally rewind master beyond what I already pushed out. "ko" shorthand points at the repository I have at kernel.org, and looks like this: -$ cat .git/remotes/ko -URL: kernel.org:/pub/scm/git/git.git -Pull: master:refs/tags/ko-master -Pull: maint:refs/tags/ko-maint -Push: master -Push: +pu -Push: maint + $ cat .git/remotes/ko + URL: kernel.org:/pub/scm/git/git.git + Pull: master:refs/tags/ko-master + Pull: maint:refs/tags/ko-maint + Push: master + Push: +pu + Push: maint +In the output from "git show-branch", "master" should have +everything "ko-master" has. <12> push out the bleeding edge. <13> push the tag out, too. ------------ @@ -357,8 +361,8 @@ and maintain access to the repository by developers. * gitlink:git-shell[1] can be used as a 'restricted login shell' for shared central repository users. - * link:howto/update-hook-example.txt[update hook howto] has a - good example of managing a shared central repository. +link:howto/update-hook-example.txt[update hook howto] has a good +example of managing a shared central repository. Examples -- cgit v1.3 From 3af849a3dae9442767668cd2045e360225724558 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 19 Dec 2005 00:31:08 -0800 Subject: howto/using-topic-branches: Recommend public URL git://git.kernel.org/ Recommending this means subsystem maintainers do not have to log-in just to resync with upstream. Signed-off-by: Junio C Hamano --- Documentation/howto/using-topic-branches.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/howto/using-topic-branches.txt b/Documentation/howto/using-topic-branches.txt index 494429738f..b3d592fc3e 100644 --- a/Documentation/howto/using-topic-branches.txt +++ b/Documentation/howto/using-topic-branches.txt @@ -42,8 +42,7 @@ So here is the step-by-step guide how this all works for me. First create your work tree by cloning Linus's public tree: - $ git clone \ - master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work + $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work Change directory into the cloned tree you just created @@ -53,7 +52,7 @@ Set up a remotes file so that you can fetch the latest from Linus' master branch into a local branch named "linus": $ cat > .git/remotes/linus - URL: master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + URL: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git Pull: master:linus ^D -- cgit v1.3 From 42f4570c86c41c5bfdc72465afc8f1928da69eea Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 18 Dec 2005 17:23:50 -0800 Subject: Documentation/git-archimport: document -o, -a, f, -D options Also, ensure usage help switches are in the same order. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- Documentation/git-archimport.txt | 23 ++++++++++++++++++++++- git-archimport.perl | 5 +++-- 2 files changed, 25 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.txt index fcda0125af..a2bd788f37 100644 --- a/Documentation/git-archimport.txt +++ b/Documentation/git-archimport.txt @@ -8,7 +8,8 @@ git-archimport - Import an Arch repository into git SYNOPSIS -------- -`git-archimport` [ -h ] [ -v ] [ -T ] [ -t tempdir ] +`git-archimport` [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] + [ -D depth ] [ -t tempdir ] [ ] DESCRIPTION @@ -63,6 +64,26 @@ OPTIONS Many tags. Will create a tag for every commit, reflecting the commit name in the Arch repository. +-f:: + Use the fast patchset import strategy. This can be significantly + faster for large trees, but cannot handle directory renames or + permissions changes. The default strategy is slow and safe. + +-o:: + Use this for compatibility with old-style branch names used by + earlier versions of git-archimport. Old-style branch names + were category--branch, whereas new-style branch names are + archive,category--branch--version. + +-D :: + Follow merge ancestry and attempt to import trees that have been + merged from. Specify a depth greater than 1 if patch logs have been + pruned. + +-a:: + Attempt to auto-register archives at http://mirrors.sourcecontrol.net + This is particularly useful with the -D option. + -t :: Override the default tempdir. diff --git a/git-archimport.perl b/git-archimport.perl index aab4e38440..841738d5c7 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -9,7 +9,8 @@ =head1 Invocation - git-archimport [ -h ] [ -v ] [ -T ] [ -t tempdir ] / [ / ] + git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] + [ -D depth] [ -t tempdir ] / [ / ] Imports a project from one or more Arch repositories. It will follow branches and repositories within the namespaces defined by the @@ -74,7 +75,7 @@ our($opt_h,$opt_f,$opt_v,$opt_T,$opt_t,$opt_D,$opt_a,$opt_o); sub usage() { print STDERR < Date: Mon, 19 Dec 2005 16:35:48 -0800 Subject: Documentation: stdout of update-hook is connected to /dev/null Mention that update-hook does not emit its stdout to the sender. Signed-off-by: Junio C Hamano --- Documentation/hooks.txt | 8 ++++++++ Documentation/howto/rebuild-from-update-hook.txt | 8 ++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt index 7ee3571bc0..4ad1920ec1 100644 --- a/Documentation/hooks.txt +++ b/Documentation/hooks.txt @@ -111,6 +111,10 @@ Another use suggested on the mailing list is to use this hook to implement access control which is finer grained than the one based on filesystem group. +The standard output of this hook is sent to /dev/null; if you +want to report something to the git-send-pack on the other end, +you can redirect your output to your stderr. + post-update ----------- @@ -125,3 +129,7 @@ the outcome of `git-receive-pack`. The default post-update hook, when enabled, runs `git-update-server-info` to keep the information used by dumb transport up-to-date. + +The standard output of this hook is sent to /dev/null; if you +want to report something to the git-send-pack on the other end, +you can redirect your output to your stderr. diff --git a/Documentation/howto/rebuild-from-update-hook.txt b/Documentation/howto/rebuild-from-update-hook.txt index ebd025db85..02621b54a0 100644 --- a/Documentation/howto/rebuild-from-update-hook.txt +++ b/Documentation/howto/rebuild-from-update-hook.txt @@ -10,7 +10,7 @@ The pages under http://www.kernel.org/pub/software/scm/git/docs/ are built from Documentation/ directory of the git.git project and needed to be kept up-to-date. The www.kernel.org/ servers are mirrored and I was told that the origin of the mirror is on -the machine master.kernel.org, on which I was given an account +the machine $some.kernel.org, on which I was given an account when I took over git maintainership from Linus. The directories relevant to this how-to are these two: @@ -63,7 +63,7 @@ like this: EOF $ chmod +x /pub/scm/git/git.git/hooks/post-update -There are three things worth mentioning: +There are four things worth mentioning: - The update-hook is run after the repository accepts a "git push", under my user privilege. It is given the full names @@ -77,6 +77,10 @@ There are three things worth mentioning: pull" it does into $HOME/doc-git/docgen/ repository would not work correctly. + - The stdout of update hook script is not connected to git + push; I run the heavy part of the command inside "at", to + receive the execution report via e-mail. + - This is still crude and does not protect against simultaneous make invocations stomping on each other. I would need to add some locking mechanism for this. -- cgit v1.3 From e32faa8adbc8ba9803088e849bc26680134c853c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 19 Dec 2005 18:03:31 -0800 Subject: Remove "octopus". We still advertise "git resolve" as a standalone command, but never "git octopus", so nobody should be using it and it is safe to retire it. The functionality is still available as a strategy backend. Signed-off-by: Junio C Hamano --- .gitignore | 1 - Documentation/git-octopus.txt | 38 ------------------ Documentation/git.txt | 3 -- Makefile | 2 +- git-octopus.sh | 90 ------------------------------------------- 5 files changed, 1 insertion(+), 133 deletions(-) delete mode 100644 Documentation/git-octopus.txt delete mode 100755 git-octopus.sh (limited to 'Documentation') diff --git a/.gitignore b/.gitignore index 8a6bd02d4f..6bd508e4be 100644 --- a/.gitignore +++ b/.gitignore @@ -60,7 +60,6 @@ git-merge-stupid git-mktag git-name-rev git-mv -git-octopus git-pack-redundant git-pack-objects git-parse-remote diff --git a/Documentation/git-octopus.txt b/Documentation/git-octopus.txt deleted file mode 100644 index 6e32ea347c..0000000000 --- a/Documentation/git-octopus.txt +++ /dev/null @@ -1,38 +0,0 @@ -git-octopus(1) -============== - -NAME ----- -git-octopus - Merge more than two commits. - - -SYNOPSIS --------- -'git-octopus' - -DESCRIPTION ------------ -After running 'git fetch', $GIT_DIR/FETCH_HEAD contains the -following information, one line per remote ref: - ------------------------------------------------- - from ------------------------------------------------- - -Using this information, create and commit an Octopus merge on -top of the current HEAD. - - -Author ------- -Written by Junio C Hamano - - -Documentation --------------- -Documentation by Junio C Hamano and the git-list . - -GIT ---- -Part of the gitlink:git[7] suite - diff --git a/Documentation/git.txt b/Documentation/git.txt index 482eba7eba..5f068c2a1a 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -297,9 +297,6 @@ gitlink:git-merge[1]:: gitlink:git-mv[1]:: Move or rename a file, a directory, or a symlink. -gitlink:git-octopus[1]:: - Merge more than two commits. - gitlink:git-pull[1]:: Fetch from and merge with a remote repository. diff --git a/Makefile b/Makefile index c66220c1a6..50392ff651 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ SCRIPT_SH = \ git-cherry.sh git-clone.sh git-commit.sh \ git-count-objects.sh git-diff.sh git-fetch.sh \ git-format-patch.sh git-log.sh git-ls-remote.sh \ - git-merge-one-file.sh git-octopus.sh git-parse-remote.sh \ + git-merge-one-file.sh git-parse-remote.sh \ git-prune.sh git-pull.sh git-push.sh git-rebase.sh \ git-repack.sh git-request-pull.sh git-reset.sh \ git-resolve.sh git-revert.sh git-sh-setup.sh git-status.sh \ diff --git a/git-octopus.sh b/git-octopus.sh deleted file mode 100755 index 2edbf52c42..0000000000 --- a/git-octopus.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2005 Junio C Hamano -# -# Resolve two or more trees recorded in $GIT_DIR/FETCH_HEAD. -# -. git-sh-setup - -usage () { - die "usage: git octopus" -} - -# Sanity check the heads early. -while read SHA1 REPO -do - test $(git-cat-file -t $SHA1) = "commit" || - die "$REPO given to octopus is not a commit" -done <"$GIT_DIR/FETCH_HEAD" - -head=$(git-rev-parse --verify HEAD) || exit - -git-update-index --refresh || - die "Your working tree is dirty." -test "$(git-diff-index --cached "$head")" = "" || - die "Your working tree does not match HEAD." - -# MRC is the current "merge reference commit" -# MRT is the current "merge result tree" - -MRC=$head PARENT="-p $head" -MRT=$(git-write-tree) -CNT=1 ;# counting our head -NON_FF_MERGE=0 -while read SHA1 REPO -do - common=$(git-merge-base $MRC $SHA1) || - die "Unable to find common commit with $SHA1 from $REPO" - - if test "$common" = $SHA1 - then - echo "Already up-to-date: $REPO" - continue - fi - - CNT=`expr $CNT + 1` - PARENT="$PARENT -p $SHA1" - - if test "$common,$NON_FF_MERGE" = "$MRC,0" - then - # The first head being merged was a fast-forward. - # Advance MRC to the head being merged, and use that - # tree as the intermediate result of the merge. - # We still need to count this as part of the parent set. - - echo "Fast forwarding to: $REPO" - git-read-tree -u -m $head $SHA1 || exit - MRC=$SHA1 MRT=$(git-write-tree) - continue - fi - - NON_FF_MERGE=1 - - echo "Trying simple merge with $REPO" - git-read-tree -u -m $common $MRT $SHA1 || exit - next=$(git-write-tree 2>/dev/null) - if test $? -ne 0 - then - echo "Simple merge did not work, trying automatic merge." - git-merge-index -o git-merge-one-file -a || { - git-read-tree --reset "$head" - git-checkout-index -f -q -u -a - die "Automatic merge failed; should not be doing Octopus" - } - next=$(git-write-tree 2>/dev/null) - fi - MRC=$common - MRT=$next -done <"$GIT_DIR/FETCH_HEAD" - -# Just to be careful in case the user feeds nonsense to us. -case "$CNT" in -1) - echo "No changes." - exit 0 ;; -esac -result_commit=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD" | - git-commit-tree $MRT $PARENT) -echo "Committed merge $result_commit" -git-update-ref HEAD $result_commit $head -git-diff-tree -p $head $result_commit | git-apply --stat -- cgit v1.3 From 47dd0d595d04ee5283dfd8a0b4cbd6e6de8ad57f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 13 Dec 2005 17:21:41 -0800 Subject: diff: --abbrev option When I show transcripts to explain how something works, I often find myself hand-editing the diff-raw output to shorten various object names in the output. This adds --abbrev option to the diff family, which shortens diff-raw output and diff-tree commit id headers. Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 7 ++++++ diff-tree.c | 40 +++++++++++++++++------------ diff.c | 57 +++++++++++++++++++++++++++++++++++++----- diff.h | 9 ++++++- sha1_name.c | 3 +++ 5 files changed, 93 insertions(+), 23 deletions(-) (limited to 'Documentation') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 6b496ede25..3d1175e864 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -18,6 +18,13 @@ object name of pre- and post-image blob on the "index" line when generating a patch format output. +--abbrev:: + Instead of showing the full 40-byte hexadecimal object + name in diff-raw format output and diff-tree header + lines, show only handful prefix. This is independent of + --full-index option above, which controls the diff-patch + output format. + -B:: Break complete rewrite changes into pairs of delete and create. diff --git a/diff-tree.c b/diff-tree.c index d56d921585..efa2b9476e 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -14,11 +14,6 @@ static enum cmit_fmt commit_format = CMIT_FMT_RAW; static struct diff_options diff_options; -static void call_diff_setup_done(void) -{ - diff_setup_done(&diff_options); -} - static int call_diff_flush(void) { diffcore_std(&diff_options); @@ -43,7 +38,6 @@ static int diff_tree_sha1_top(const unsigned char *old, { int ret; - call_diff_setup_done(); ret = diff_tree_sha1(old, new, base, &diff_options); call_diff_flush(); return ret; @@ -55,7 +49,6 @@ static int diff_root_tree(const unsigned char *new, const char *base) void *tree; struct tree_desc empty, real; - call_diff_setup_done(); tree = read_object_with_reference(new, "tree", &real.size, NULL); if (!tree) die("unable to read root tree (%s)", sha1_to_hex(new)); @@ -69,18 +62,29 @@ static int diff_root_tree(const unsigned char *new, const char *base) return retval; } -static const char *generate_header(const char *commit, const char *parent, const char *msg) +static const char *generate_header(const unsigned char *commit_sha1, + const unsigned char *parent_sha1, + const char *msg) { static char this_header[16384]; int offset; unsigned long len; + int abbrev = diff_options.abbrev; if (!verbose_header) - return commit; + return sha1_to_hex(commit_sha1); len = strlen(msg); - offset = sprintf(this_header, "%s%s (from %s)\n", header_prefix, commit, parent); - offset += pretty_print_commit(commit_format, msg, len, this_header + offset, sizeof(this_header) - offset); + + offset = sprintf(this_header, "%s%s ", + header_prefix, + diff_unique_abbrev(commit_sha1, abbrev)); + offset += sprintf(this_header + offset, "(from %s)\n", + parent_sha1 ? + diff_unique_abbrev(parent_sha1, abbrev) : "root"); + offset += pretty_print_commit(commit_format, msg, len, + this_header + offset, + sizeof(this_header) - offset); return this_header; } @@ -99,18 +103,18 @@ static int diff_tree_commit(const unsigned char *commit_sha1) /* Root commit? */ if (show_root_diff && !commit->parents) { - header = generate_header(name, "root", commit->buffer); + header = generate_header(sha1, NULL, commit->buffer); diff_root_tree(commit_sha1, ""); } /* More than one parent? */ if (ignore_merges && commit->parents && commit->parents->next) - return 0; + return 0; for (parents = commit->parents; parents; parents = parents->next) { struct commit *parent = parents->item; - header = generate_header(name, - sha1_to_hex(parent->object.sha1), + header = generate_header(sha1, + parent->object.sha1, commit->buffer); diff_tree_sha1_top(parent->object.sha1, commit_sha1, ""); if (!header && verbose_header) { @@ -129,6 +133,7 @@ static int diff_tree_stdin(char *line) int len = strlen(line); unsigned char commit[20], parent[20]; static char this_header[1000]; + int abbrev = diff_options.abbrev; if (!len || line[len-1] != '\n') return -1; @@ -138,7 +143,9 @@ static int diff_tree_stdin(char *line) if (isspace(line[40]) && !get_sha1_hex(line+41, parent)) { line[40] = 0; line[81] = 0; - sprintf(this_header, "%s (from %s)\n", line, line+41); + sprintf(this_header, "%s (from %s)\n", + diff_unique_abbrev(commit, abbrev), + diff_unique_abbrev(parent, abbrev)); header = this_header; return diff_tree_sha1_top(parent, commit, ""); } @@ -239,6 +246,7 @@ int main(int argc, const char **argv) diff_options.recursive = 1; diff_tree_setup_paths(get_pathspec(prefix, argv)); + diff_setup_done(&diff_options); switch (nr_sha1) { case 0: diff --git a/diff.c b/diff.c index 2e0797bf3e..c8159183da 100644 --- a/diff.c +++ b/diff.c @@ -723,11 +723,13 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) if (memcmp(one->sha1, two->sha1, 20)) { char one_sha1[41]; - const char *index_fmt = o->full_index ? "index %s..%s" : "index %.7s..%.7s"; + int abbrev = o->full_index ? 40 : DIFF_DEFAULT_INDEX_ABBREV; memcpy(one_sha1, sha1_to_hex(one->sha1), 41); len += snprintf(msg + len, sizeof(msg) - len, - index_fmt, one_sha1, sha1_to_hex(two->sha1)); + "index %.*s..%.*s", + abbrev, one_sha1, abbrev, + sha1_to_hex(two->sha1)); if (one->mode == two->mode) len += snprintf(msg + len, sizeof(msg) - len, " %06o", one->mode); @@ -791,6 +793,8 @@ int diff_setup_done(struct diff_options *options) } if (options->setup & DIFF_SETUP_USE_SIZE_CACHE) use_size_cache = 1; + if (options->abbrev <= 0 || 40 < options->abbrev) + options->abbrev = 40; /* full */ return 0; } @@ -841,6 +845,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) } else if (!strcmp(arg, "--find-copies-harder")) options->find_copies_harder = 1; + else if (!strcmp(arg, "--abbrev")) + options->abbrev = DIFF_DEFAULT_ABBREV; + else if (!strncmp(arg, "--abbrev=", 9)) + options->abbrev = strtoul(arg + 9, NULL, 10); else return 0; return 1; @@ -947,14 +955,49 @@ void diff_free_filepair(struct diff_filepair *p) free(p); } +/* This is different from find_unique_abbrev() in that + * it needs to deal with 0{40} SHA1. + */ +const char *diff_unique_abbrev(const unsigned char *sha1, int len) +{ + int abblen; + const char *abbrev; + if (len == 40) + return sha1_to_hex(sha1); + + abbrev = find_unique_abbrev(sha1, len); + if (!abbrev) { + if (!memcmp(sha1, null_sha1, 20)) { + char *buf = sha1_to_hex(null_sha1); + if (len < 37) + strcpy(buf + len, "..."); + return buf; + } + else + return sha1_to_hex(sha1); + } + abblen = strlen(abbrev); + if (abblen < 37) { + static char hex[41]; + if (len < abblen && abblen <= len + 2) + sprintf(hex, "%s%.*s", abbrev, len+3-abblen, ".."); + else + sprintf(hex, "%s...", abbrev); + return hex; + } + return sha1_to_hex(sha1); +} + static void diff_flush_raw(struct diff_filepair *p, int line_termination, int inter_name_termination, - int output_format) + struct diff_options *options) { int two_paths; char status[10]; + int abbrev = options->abbrev; const char *path_one, *path_two; + int output_format = options->output_format; path_one = p->one->path; path_two = p->two->path; @@ -985,8 +1028,10 @@ static void diff_flush_raw(struct diff_filepair *p, } if (output_format != DIFF_FORMAT_NAME_STATUS) { printf(":%06o %06o %s ", - p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1)); - printf("%s ", sha1_to_hex(p->two->sha1)); + p->one->mode, p->two->mode, + diff_unique_abbrev(p->one->sha1, abbrev)); + printf("%s ", + diff_unique_abbrev(p->two->sha1, abbrev)); } printf("%s%c%s", status, inter_name_termination, path_one); if (two_paths) @@ -1194,7 +1239,7 @@ void diff_flush(struct diff_options *options) case DIFF_FORMAT_NAME_STATUS: diff_flush_raw(p, line_termination, inter_name_termination, - diff_output_format); + options); break; case DIFF_FORMAT_NAME: diff_flush_name(p, diff --git a/diff.h b/diff.h index 32b4780173..c3486ffa86 100644 --- a/diff.h +++ b/diff.h @@ -44,6 +44,7 @@ struct diff_options { int reverse_diff; int rename_limit; int setup; + int abbrev; change_fn_t change; add_remove_fn_t add_remove; @@ -87,6 +88,9 @@ extern int diff_setup_done(struct diff_options *); #define DIFF_PICKAXE_ALL 1 +#define DIFF_DEFAULT_INDEX_ABBREV 7 /* hex digits */ +#define DIFF_DEFAULT_ABBREV 7 /* hex digits */ + extern void diffcore_std(struct diff_options *); extern void diffcore_std_no_resolve(struct diff_options *); @@ -98,7 +102,8 @@ extern void diffcore_std_no_resolve(struct diff_options *); " -u synonym for -p.\n" \ " --name-only show only names of changed files.\n" \ " --name-status show names and status of changed files.\n" \ -" --full-index show full object name on index ines.\n" \ +" --full-index show full object name on index lines.\n" \ +" --abbrev abbreviate object names in diff-tree header and diff-raw.\n" \ " -R swap input file pairs.\n" \ " -B detect complete rewrites.\n" \ " -M detect renames.\n" \ @@ -137,4 +142,6 @@ extern void diff_flush(struct diff_options*); #define DIFF_STATUS_FILTER_AON '*' #define DIFF_STATUS_FILTER_BROKEN 'B' +extern const char *diff_unique_abbrev(const unsigned char *, int); + #endif /* DIFF_H */ diff --git a/sha1_name.c b/sha1_name.c index 67b69a54fb..b13ed78cee 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -188,7 +188,10 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len) { int status; static char hex[41]; + memcpy(hex, sha1_to_hex(sha1), 40); + if (len == 40) + return hex; while (len < 40) { unsigned char sha1_ret[20]; status = get_short_sha1(hex, len, sha1_ret, 1); -- cgit v1.3 From 913419fcc648dd43d7f7afdd94fa25aee4f9798a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 18 Dec 2005 02:03:15 -0800 Subject: diff --abbrev: document --abbrev= form. It was implemented there but was not advertised. Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 9 +++++---- diff.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 3d1175e864..9e574a04d3 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -18,12 +18,13 @@ object name of pre- and post-image blob on the "index" line when generating a patch format output. ---abbrev:: +--abbrev[=]:: Instead of showing the full 40-byte hexadecimal object name in diff-raw format output and diff-tree header - lines, show only handful prefix. This is independent of - --full-index option above, which controls the diff-patch - output format. + lines, show only handful dhexigits prefix. This is + independent of --full-index option above, which controls + the diff-patch output format. Non default number of + digits can be specified with --abbrev=. -B:: Break complete rewrite changes into pairs of delete and create. diff --git a/diff.h b/diff.h index c3486ffa86..5696f2aff0 100644 --- a/diff.h +++ b/diff.h @@ -103,7 +103,7 @@ extern void diffcore_std_no_resolve(struct diff_options *); " --name-only show only names of changed files.\n" \ " --name-status show names and status of changed files.\n" \ " --full-index show full object name on index lines.\n" \ -" --abbrev abbreviate object names in diff-tree header and diff-raw.\n" \ +" --abbrev= abbreviate object names in diff-tree header and diff-raw.\n" \ " -R swap input file pairs.\n" \ " -B detect complete rewrites.\n" \ " -M detect renames.\n" \ -- cgit v1.3 From a3431febfe241120205472def2a14ef09a4dbe60 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 20 Dec 2005 20:54:28 -0800 Subject: A shared repository should be writable by members. Signed-off-by: Junio C Hamano --- Documentation/tutorial.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index 1683f0bc2d..3a5c56e24e 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -1625,7 +1625,9 @@ cooperation you are probably more familiar with as well. For this, set up a public repository on a machine that is reachable via SSH by people with "commit privileges". Put the committers in the same user group and make the repository -writable by that group. +writable by that group. Make sure their umasks are set up to +allow group members to write into directories other members +have created. You, as an individual committer, then: -- cgit v1.3