From d7ebd53d371153f7a61c0fe9f384c9662b751bf6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 23 Jan 2007 16:51:22 -0800 Subject: [PATCH 01/14] git-checkout -m: fix merge case Commit c1a4278e switched the "merging checkout" implementation from 3-way read-tree to merge-recursive, but forgot that merge-recursive will signal an unmerged state with its own exit status code. This prevented the clean-up phase (paths cleanly merged should not be updated in the index) from running. Signed-off-by: Junio C Hamano --- git-checkout.sh | 15 +++++---------- t/t7201-co.sh | 28 +++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/git-checkout.sh b/git-checkout.sh index e02d4d87f6..c52f352f08 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -200,17 +200,12 @@ else # Match the index to the working tree, and do a three-way. git diff-files --name-only | git update-index --remove --stdin && work=`git write-tree` && - git read-tree --reset -u $new && - eval GITHEAD_$new=${new_name:-${branch:-$new}} GITHEAD_$work=local && - export GITHEAD_$new GITHEAD_$work && - git merge-recursive $old -- $new $work || exit + git read-tree --reset -u $new || exit - if result=`git write-tree 2>/dev/null` - then - echo >&2 "Trivially automerged." - else - git merge-index -o git-merge-one-file -a - fi + eval GITHEAD_$new=${new_name:-${branch:-$new}} && + eval GITHEAD_$work=local && + export GITHEAD_$new GITHEAD_$work && + git merge-recursive $old -- $new $work # Do not register the cleanly merged paths in the index yet. # this is not a real merge before committing, but just carrying diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 315fa3564c..867bbd26cb 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -100,7 +100,33 @@ test_expect_success "checkout -m with dirty tree, renamed" ' git checkout -m renamer && fill 1 3 4 5 7 8 >expect && diff expect uno && - ! test -f one + ! test -f one && + git diff --cached >current && + ! test -s current + +' + +test_expect_success 'checkout -m with merge conflict' ' + + git checkout -f master && git clean && + + fill 1 T 3 4 5 6 S 8 >one && + if git checkout renamer + then + echo Not happy + false + else + echo "happy - failed correctly" + fi && + + git checkout -m renamer && + + git diff master:one :3:uno | + sed -e "1,/^@@/d" -e "/^ /d" -e "s/^-/d/" -e "s/^+/a/" >current && + fill d2 aT d7 aS >expect && + diff current expect && + git diff --cached two >current && + ! test -s current ' test_done From 83cd10a05688e6429f9e65cffbe90683e9487800 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 23 Jan 2007 13:37:25 +0100 Subject: [PATCH 02/14] t/t1300-repo-config.sh: value continued on next line Documentation/config.txt: Variable value ending in a '`\`' is continued on the next line in the customary UNIX fashion. Test it. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- t/t1300-repo-config.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index eb7455ba21..0e4f32d5c9 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -424,5 +424,25 @@ newline 123' test_expect_success 'value with newline' 'git repo-config key.sub value.with\\\ newline' +cat > .git/config <<\EOF +[section] + ; comment \ + continued = cont\ +inued + noncont = not continued ; \ + quotecont = "cont;\ +inued" +EOF + +cat > expect <<\EOF +section.continued=continued +section.noncont=not continued +section.quotecont=cont;inued +EOF + +git repo-config --list > result + +test_expect_success 'value continued on next line' 'cmp result expect' + test_done From e955ae957c401cb541f23d46af66c9b3d5b8ffe9 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 24 Jan 2007 15:04:37 +0100 Subject: [PATCH 03/14] annotate: use pager Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- git.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git.c b/git.c index 72a1486f30..530e99fe64 100644 --- a/git.c +++ b/git.c @@ -214,7 +214,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp) int option; } commands[] = { { "add", cmd_add, RUN_SETUP | NOT_BARE }, - { "annotate", cmd_annotate, }, + { "annotate", cmd_annotate, USE_PAGER }, { "apply", cmd_apply }, { "archive", cmd_archive }, { "blame", cmd_blame, RUN_SETUP | USE_PAGER }, From 084ae0a7bd8a13dea7731dd7b6bf37f08c1cfc77 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 24 Jan 2007 15:05:16 +0100 Subject: [PATCH 04/14] reflog inspection: introduce shortcut "-g" A short-hand "-g" for "git log --walk-reflogs" and "git show-branch --reflog" makes it easier to access the reflog info. [jc: added -g to show-branch for symmetry] Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/git-rev-list.txt | 2 +- Documentation/git-show-branch.txt | 6 +++--- builtin-show-branch.c | 4 +++- revision.c | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index a996f6cb1e..c742117595 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -191,7 +191,7 @@ limiting may be applied. In addition to the '' listed on the command line, read them from the standard input. ---walk-reflogs:: +-g, --walk-reflogs:: Instead of walking the commit ancestry chain, walk reflog entries from the most recent one to older ones. diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt index 529f3a648a..b38633c397 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.txt @@ -11,7 +11,7 @@ SYNOPSIS 'git-show-branch' [--all] [--remotes] [--topo-order] [--current] [--more= | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [ | ]... -'git-show-branch' --reflog[=[,]] [--list] +'git-show-branch' (-g|--reflog)[=[,]] [--list] DESCRIPTION ----------- @@ -100,8 +100,8 @@ OPTIONS --reflog[=[,]] :: Shows most recent ref-log entries for the given ref. If is given, entries going back from - that entry. can be specified as count or date - + that entry. can be specified as count or date. + `-g` can be used as a short-hand for this option. Note that --more, --list, --independent and --merge-base options are mutually exclusive. diff --git a/builtin-show-branch.c b/builtin-show-branch.c index b54c410e14..536245e7d3 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -649,11 +649,13 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) dense = 0; else if (!strcmp(arg, "--date-order")) lifo = 0; - else if (!strcmp(arg, "--reflog")) { + else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) { reflog = DEFAULT_REFLOG; } else if (!strncmp(arg, "--reflog=", 9)) parse_reflog_param(arg + 9, &reflog, &reflog_base); + else if (!strncmp(arg, "-g=", 3)) + parse_reflog_param(arg + 3, &reflog, &reflog_base); else usage(show_branch_usage); ac--; av++; diff --git a/revision.c b/revision.c index ebd025064c..5bcd155e21 100644 --- a/revision.c +++ b/revision.c @@ -868,7 +868,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch handle_reflog(revs, flags); continue; } - if (!strcmp(arg, "--walk-reflogs")) { + if (!strcmp(arg, "-g") || + !strcmp(arg, "--walk-reflogs")) { init_reflog_walk(&revs->reflog_info); continue; } From eda95d9969d9fbd23a80c2261299098f16bea611 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 24 Jan 2007 15:29:07 -0800 Subject: [PATCH 05/14] git-daemon documentation on enabling services. Noticed by Franck Bui-Huu. Signed-off-by: Junio C Hamano --- Documentation/git-daemon.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt index 993adc7c5a..9ddab71203 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@ -131,14 +131,14 @@ Giving these options is an error when used with `--inetd`; use the facility of inet daemon to achieve the same before spawning `git-daemon` if needed. ---enable-service, --disable-service:: +--enable=service, --disable=service:: Enable/disable the service site-wide per default. Note that a service disabled site-wide can still be enabled per repository if it is marked overridable and the repository enables the service with an configuration item. ---allow-override, --forbid-override:: +--allow-override=service, --forbid-override=service:: Allow/forbid overriding the site-wide default with per repository configuration. By default, all the services are overridable. From 191453f66449537da29e9fc156f7a981845ea8f6 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Wed, 24 Jan 2007 15:14:33 +0100 Subject: [PATCH 06/14] Documentation/config.txt: Correct info about subsection name Contrary to variable values, in subsection names parsing character escape codes (besides literal escaping of " as \", and \ as \\) is not performed; subsection name cannot contain newlines. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- Documentation/config.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 77a2b16416..d8244b1510 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -37,8 +37,8 @@ in the section header, like in example below: -------- -Subsection names can contain any characters (doublequote '`"`', backslash -'`\`' and newline have to be entered escaped as '`\"`', '`\\`' and '`\n`', +Subsection names can contain any characters except newline (doublequote +'`"`' and backslash have to be escaped as '`\"`' and '`\\`', respecitvely) and are case sensitive. Section header cannot span multiple lines. Variables may belong directly to a section or to a given subsection. You can have `[section]` if you have `[section "subsection"]`, but you From 497171e765b7b4f903d21379bee050380e539cf3 Mon Sep 17 00:00:00 2001 From: Peter Eriksen Date: Wed, 24 Jan 2007 20:54:46 +0100 Subject: [PATCH 07/14] Documentation: --amend cannot be combined with -c/-C/-F. We used to get the following confusing error message: $ git commit --amend -a -m foo Option -m cannot be combined with -c/-C/-F This is because --amend cannot be combined with -c/-C/-F, which makes sense, because they try to handle the same log message in different ways. So update the documentation to reflect this. Signed-off-by: Peter Eriksen Signed-off-by: Junio C Hamano --- Documentation/git-commit.txt | 4 ++-- git-commit.sh | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 532703a674..2187eee416 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -8,8 +8,8 @@ git-commit - Record changes to the repository SYNOPSIS -------- [verse] -'git-commit' [-a] [-s] [-v] [(-c | -C) | -F | -m ] - [--no-verify] [--amend] [-e] [--author ] +'git-commit' [-a] [-s] [-v] [(-c | -C) | -F | -m | + --amend] [--no-verify] [-e] [--author ] [--] [[-i | -o ]...] DESCRIPTION diff --git a/git-commit.sh b/git-commit.sh index 6f4dcdbccc..d8c236b240 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Linus Torvalds # Copyright (c) 2006 Junio C Hamano -USAGE='[-a] [-s] [-v] [--no-verify] [-m | -F | (-C|-c) ] [-u] [--amend] [-e] [--author ] [[-i | -o] ...]' +USAGE='[-a] [-s] [-v] [--no-verify] [-m | -F | (-C|-c) | --amend] [-u] [-e] [--author ] [[-i | -o] ...]' SUBDIRECTORY_OK=Yes . git-sh-setup require_work_tree @@ -284,9 +284,9 @@ esac case "$log_given" in tt*) - die "Only one of -c/-C/-F can be used." ;; + die "Only one of -c/-C/-F/--amend can be used." ;; *tm*|*mt*) - die "Option -m cannot be combined with -c/-C/-F." ;; + die "Option -m cannot be combined with -c/-C/-F/--amend." ;; esac case "$#,$also,$only,$amend" in From 27dca07fb77f6f5851e3a8de54f86c803358caa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 23 Jan 2007 09:20:17 +0100 Subject: [PATCH 08/14] rename --exec to --upload-pack for fetch-pack and peek-remote MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just some option name disambiguation. This is the counter part to commit d23842fd which made a similar change for push and send-pack. --exec continues to work. Signed-off-by: Uwe Kleine-König Signed-off-by: Junio C Hamano --- Documentation/git-fetch-pack.txt | 7 +++++-- Documentation/git-peek-remote.txt | 7 +++++-- fetch-pack.c | 12 ++++++++---- peek-remote.c | 12 ++++++++---- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index bd8ebacd7d..105d76b0ba 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' [--all] [--quiet|-q] [--keep|-k] [--thin] [--exec=] [--depth=] [-v] [:] [...] +'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=] [--depth=] [-v] [:] [...] DESCRIPTION ----------- @@ -45,7 +45,7 @@ OPTIONS Spend extra cycles to minimize the number of objects to be sent. Use it on slower connection. -\--exec=:: +\--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 @@ -57,6 +57,9 @@ OPTIONS shells by having a lean .bashrc file (they set most of the things up in .bash_profile). +\--exec=:: + Same as \--upload-pack=. + \--depth=:: Limit fetching to ancestor-chains not longer than n. diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt index ac57cda3a5..74f37bd904 100644 --- a/Documentation/git-peek-remote.txt +++ b/Documentation/git-peek-remote.txt @@ -8,7 +8,7 @@ git-peek-remote - List the references in a remote repository SYNOPSIS -------- -'git-peek-remote' [--exec=] [:] +'git-peek-remote' [--upload-pack=] [:] DESCRIPTION ----------- @@ -17,7 +17,7 @@ stores them in the local repository under the same name. OPTIONS ------- ---exec=:: +\--upload-pack=:: Use this to specify the path to 'git-upload-pack' on the remote side, if it is not found on your $PATH. Some installations of sshd ignores the user's environment @@ -29,6 +29,9 @@ OPTIONS shells, but prefer having a lean .bashrc file (they set most of the things up in .bash_profile). +\--exec=:: + Same \--upload-pack=. + :: A remote host that houses the repository. When this part is specified, 'git-upload-pack' is invoked via diff --git a/fetch-pack.c b/fetch-pack.c index 726140a1a5..3546aef7bc 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -12,8 +12,8 @@ static int verbose; static int fetch_all; static int depth; static const char fetch_pack_usage[] = -"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--exec=] [--depth=] [-v] [:] [...]"; -static const char *exec = "git-upload-pack"; +"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=] [--depth=] [-v] [:] [...]"; +static const char *uploadpack = "git-upload-pack"; #define COMPLETE (1U << 0) #define COMMON (1U << 1) @@ -643,8 +643,12 @@ int main(int argc, char **argv) char *arg = argv[i]; if (*arg == '-') { + if (!strncmp("--upload-pack=", arg, 14)) { + uploadpack = arg + 14; + continue; + } if (!strncmp("--exec=", arg, 7)) { - exec = arg + 7; + uploadpack = arg + 7; continue; } if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) { @@ -682,7 +686,7 @@ int main(int argc, char **argv) } if (!dest) usage(fetch_pack_usage); - pid = git_connect(fd, dest, exec); + pid = git_connect(fd, dest, uploadpack); if (pid < 0) return 1; if (heads && nr_heads) diff --git a/peek-remote.c b/peek-remote.c index 353da002b4..ef3c76ce52 100644 --- a/peek-remote.c +++ b/peek-remote.c @@ -3,8 +3,8 @@ #include "pkt-line.h" static const char peek_remote_usage[] = -"git-peek-remote [--exec=upload-pack] [host:]directory"; -static const char *exec = "git-upload-pack"; +"git-peek-remote [--upload-pack=] [:]"; +static const char *uploadpack = "git-upload-pack"; static int peek_remote(int fd[2], unsigned flags) { @@ -35,8 +35,12 @@ int main(int argc, char **argv) char *arg = argv[i]; if (*arg == '-') { + if (!strncmp("--upload-pack=", arg, 14)) { + uploadpack = arg + 14; + continue; + } if (!strncmp("--exec=", arg, 7)) { - exec = arg + 7; + uploadpack = arg + 7; continue; } if (!strcmp("--tags", arg)) { @@ -60,7 +64,7 @@ int main(int argc, char **argv) if (!dest || i != argc - 1) usage(peek_remote_usage); - pid = git_connect(fd, dest, exec); + pid = git_connect(fd, dest, uploadpack); if (pid < 0) return 1; ret = peek_remote(fd, flags); From ae1dffcb28ee89a23f8d2747be65e17c8eab1690 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 23 Jan 2007 00:51:53 -0800 Subject: [PATCH 09/14] ls-remote and clone: accept --upload-pack= as well. This makes them consistent with other commands that take the path to the upload-pack program. We also pass --upload-pack instead of --exec to the underlying fetch-pack, although it is not strictly necessary. [jc: original motivation from Uwe] Signed-off-by: Junio C Hamano --- git-clone.sh | 4 +++- git-fetch.sh | 11 +++++++---- git-ls-remote.sh | 6 +++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/git-clone.sh b/git-clone.sh index 0f7bbbfb39..ced7dfba3e 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -163,7 +163,9 @@ while 1,-u|1,--upload-pack) usage ;; *,-u|*,--upload-pack) shift - upload_pack="--exec=$1" ;; + upload_pack="--upload-pack=$1" ;; + *,--upload-pack=*) + upload_pack=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)') ;; 1,--depth) usage;; *,--depth) shift diff --git a/git-fetch.sh b/git-fetch.sh index 87b940b85b..07a1d05ac7 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -22,7 +22,6 @@ force= verbose= update_head_ok= exec= -upload_pack= keep= shallow_depth= while case "$#" in 0) break ;; esac @@ -34,8 +33,12 @@ do --upl|--uplo|--uploa|--upload|--upload-|--upload-p|\ --upload-pa|--upload-pac|--upload-pack) shift - exec="--exec=$1" - upload_pack="-u $1" + exec="--upload-pack=$1" + ;; + --upl=*|--uplo=*|--uploa=*|--upload=*|\ + --upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*) + exec=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)') + shift ;; -f|--f|--fo|--for|--forc|--force) force=t @@ -94,7 +97,7 @@ then fi # Global that is reused later -ls_remote_result=$(git ls-remote $upload_pack "$remote") || +ls_remote_result=$(git ls-remote $exec "$remote") || die "Cannot get the repository state from $remote" append_fetch_head () { diff --git a/git-ls-remote.sh b/git-ls-remote.sh index 03b624ef33..dd22783824 100755 --- a/git-ls-remote.sh +++ b/git-ls-remote.sh @@ -23,7 +23,11 @@ do -u|--u|--up|--upl|--uploa|--upload|--upload-|--upload-p|--upload-pa|\ --upload-pac|--upload-pack) shift - exec="--exec=$1" + exec="--upload-pack=$1" + shift;; + -u=*|--u=*|--up=*|--upl=*|--uplo=*|--uploa=*|--upload=*|\ + --upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*) + exec=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)') shift;; --) shift; break ;; From 196055c2dbbd8ee41b4afb1c2d035d0c05c963b8 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Tue, 23 Jan 2007 16:51:18 +0100 Subject: [PATCH 10/14] Allow default core.logallrefupdates to be overridden with template's config Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- builtin-init-db.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/builtin-init-db.c b/builtin-init-db.c index 8e7540b692..1865489381 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -257,7 +257,9 @@ static int create_default_files(const char *git_dir, const char *template_path) } else { git_config_set("core.bare", "false"); - git_config_set("core.logallrefupdates", "true"); + /* allow template config file to override the default */ + if (log_all_ref_updates == -1) + git_config_set("core.logallrefupdates", "true"); } return reinit; } From a69e542989d0aa1576a4b6820454b9b0d2636796 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 22 Jan 2007 21:55:18 -0800 Subject: [PATCH 11/14] Refactor the pack header reading function out of receive-pack.c Signed-off-by: Junio C Hamano --- pack.h | 5 +++++ receive-pack.c | 26 ++++++++++++++------------ sha1_file.c | 21 +++++++++++++++++++++ 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/pack.h b/pack.h index 821706fbcd..deb427edbe 100644 --- a/pack.h +++ b/pack.h @@ -44,4 +44,9 @@ struct pack_header { #define PACK_IDX_SIGNATURE 0xff744f63 /* "\377tOc" */ extern int verify_pack(struct packed_git *, int); + +#define PH_ERROR_EOF (-1) +#define PH_ERROR_PACK_SIGNATURE (-2) +#define PH_ERROR_PROTOCOL (-3) +extern int read_pack_header(int fd, struct pack_header *); #endif diff --git a/receive-pack.c b/receive-pack.c index 6333f00c6e..b3a4552692 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -250,20 +250,22 @@ static void read_head_info(void) static const char *parse_pack_header(struct pack_header *hdr) { - char *c = (char*)hdr; - ssize_t remaining = sizeof(struct pack_header); - do { - ssize_t r = xread(0, c, remaining); - if (r <= 0) - return "eof before pack header was fully read"; - remaining -= r; - c += r; - } while (remaining > 0); - if (hdr->hdr_signature != htonl(PACK_SIGNATURE)) + switch (read_pack_header(0, hdr)) { + case PH_ERROR_EOF: + return "eof before pack header was fully read"; + + case PH_ERROR_PACK_SIGNATURE: return "protocol error (pack signature mismatch detected)"; - if (!pack_version_ok(hdr->hdr_version)) + + case PH_ERROR_PROTOCOL: return "protocol error (pack version unsupported)"; - return NULL; + + default: + return "unknown error in parse_pack_header"; + + case 0: + return NULL; + } } static const char *pack_lockfile; diff --git a/sha1_file.c b/sha1_file.c index 43ff402380..498665e50c 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2048,3 +2048,24 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write } return 0; } + +int read_pack_header(int fd, struct pack_header *header) +{ + char *c = (char*)header; + ssize_t remaining = sizeof(struct pack_header); + do { + ssize_t r = xread(fd, c, remaining); + if (r <= 0) + /* "eof before pack header was fully read" */ + return PH_ERROR_EOF; + remaining -= r; + c += r; + } while (remaining > 0); + if (header->hdr_signature != htonl(PACK_SIGNATURE)) + /* "protocol error (pack signature mismatch detected)" */ + return PH_ERROR_PACK_SIGNATURE; + if (!pack_version_ok(header->hdr_version)) + /* "protocol error (pack version unsupported)" */ + return PH_ERROR_PROTOCOL; + return 0; +} From 9e10fd1ac0bb50202138efb9291568160dacd7ab Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 22 Jan 2007 22:37:33 -0800 Subject: [PATCH 12/14] Allow fetch-pack to decide keeping the fetched pack without exploding With --keep-auto option, fetch-pack decides to keep the pack without exploding it just like receive-pack does. We may want to later make this the default. Signed-off-by: Junio C Hamano --- fetch-pack.c | 91 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/fetch-pack.c b/fetch-pack.c index 3546aef7bc..dd67e48fc7 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -4,9 +4,11 @@ #include "commit.h" #include "tag.h" #include "exec_cmd.h" +#include "pack.h" #include "sideband.h" static int keep_pack; +static int keep_auto; static int quiet; static int verbose; static int fetch_all; @@ -486,13 +488,58 @@ static pid_t setup_sideband(int fd[2], int xd[2]) return side_pid; } -static int get_pack(int xd[2], const char **argv) +static int get_pack(int xd[2]) { int status; pid_t pid, side_pid; int fd[2]; + const char *argv[20]; + char keep_arg[256]; + char hdr_arg[256]; + const char **av; + int do_keep = keep_pack; side_pid = setup_sideband(fd, xd); + + av = argv; + *hdr_arg = 0; + if (keep_auto) { + struct pack_header header; + + if (read_pack_header(fd[0], &header)) + die("protocol error: bad pack header"); + snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u", + ntohl(header.hdr_version), ntohl(header.hdr_entries)); + if (ntohl(header.hdr_entries) < keep_auto) + do_keep = 0; + else + do_keep = 1; + } + + if (do_keep) { + *av++ = "index-pack"; + *av++ = "--stdin"; + if (!quiet) + *av++ = "-v"; + if (use_thin_pack) + *av++ = "--fix-thin"; + if (keep_pack > 1 || keep_auto) { + int s = sprintf(keep_arg, + "--keep=fetch-pack %d on ", getpid()); + if (gethostname(keep_arg + s, sizeof(keep_arg) - s)) + strcpy(keep_arg + s, "localhost"); + *av++ = keep_arg; + } + } + else { + *av++ = "unpack-objects"; + if (quiet) + *av++ = "-q"; + } + if (*hdr_arg) + *av++ = hdr_arg; + *av++ = NULL; + pid = fork(); if (pid < 0) die("fetch-pack: unable to fork off %s", argv[0]); @@ -522,39 +569,10 @@ static int get_pack(int xd[2], const char **argv) die("%s died of unnatural causes %d", argv[0], status); } -static int explode_rx_pack(int xd[2]) -{ - const char *argv[3] = { "unpack-objects", quiet ? "-q" : NULL, NULL }; - return get_pack(xd, argv); -} - -static int keep_rx_pack(int xd[2]) -{ - const char *argv[6]; - char keep_arg[256]; - int n = 0; - - argv[n++] = "index-pack"; - argv[n++] = "--stdin"; - if (!quiet) - argv[n++] = "-v"; - if (use_thin_pack) - argv[n++] = "--fix-thin"; - if (keep_pack > 1) { - int s = sprintf(keep_arg, "--keep=fetch-pack %i on ", getpid()); - if (gethostname(keep_arg + s, sizeof(keep_arg) - s)) - strcpy(keep_arg + s, "localhost"); - argv[n++] = keep_arg; - } - argv[n] = NULL; - return get_pack(xd, argv); -} - static int fetch_pack(int fd[2], int nr_match, char **match) { struct ref *ref; unsigned char sha1[20]; - int status; get_remote_heads(fd[0], &ref, 0, NULL, 0); if (is_repository_shallow() && !server_supports("shallow")) @@ -589,8 +607,7 @@ static int fetch_pack(int fd[2], int nr_match, char **match) */ fprintf(stderr, "warning: no common commits\n"); - status = (keep_pack) ? keep_rx_pack(fd) : explode_rx_pack(fd); - if (status) + if (get_pack(fd)) die("git-fetch-pack: fetch failed."); all_done: @@ -659,6 +676,16 @@ int main(int argc, char **argv) keep_pack++; continue; } + if (!strcmp("--keep-auto", arg)) { + keep_auto = 100; + continue; + } + if (!strncmp("--keep-auto=", arg, 12)) { + keep_auto = strtoul(arg + 12, NULL, 0); + if (keep_auto < 20) + keep_auto = 20; + continue; + } if (!strcmp("--thin", arg)) { use_thin_pack = 1; continue; From af7cf268f0bf8d4216f9c11d1cb0082cb3550f61 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 24 Jan 2007 16:47:24 -0800 Subject: [PATCH 13/14] fetch-pack: remove --keep-auto and make it the default. This makes git-fetch over git native protocol to automatically decide to keep the downloaded pack if the fetch results in more than 100 objects, just like receive-pack invoked by git-push does. This logic is disabled when --keep is explicitly given from the command line, so that a very small clone still keeps the downloaded pack as before. The 100 threshold can be adjusted with fetch.unpacklimit configuration. We might want to introduce transfer.unpacklimit to consolidate the two unpacklimit variables, which will be a topic for the next patch. Signed-off-by: Junio C Hamano --- Documentation/config.txt | 10 ++++++++++ fetch-pack.c | 31 +++++++++++++++++-------------- t/t5500-fetch-pack.sh | 3 ++- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index d8244b1510..383ff29f82 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -295,6 +295,16 @@ diff.renames:: will enable basic rename detection. If set to "copies" or "copy", it will detect copies, as well. +fetch.unpackLimit:: + If the number of objects fetched over the git native + transfer is below this + limit, then the objects will be unpacked into loose object + files. However if the number of received objects equals or + exceeds this limit then the received pack will be stored as + a pack, after adding any missing delta bases. Storing the + pack from a push can make the push operation complete faster, + especially on slow filesystems. + format.headers:: Additional email headers to include in a patch to be submitted by mail. See gitlink:git-format-patch[1]. diff --git a/fetch-pack.c b/fetch-pack.c index dd67e48fc7..fc0534ce03 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -8,7 +8,7 @@ #include "sideband.h" static int keep_pack; -static int keep_auto; +static int unpack_limit = 100; static int quiet; static int verbose; static int fetch_all; @@ -503,14 +503,14 @@ static int get_pack(int xd[2]) av = argv; *hdr_arg = 0; - if (keep_auto) { + if (unpack_limit) { struct pack_header header; if (read_pack_header(fd[0], &header)) die("protocol error: bad pack header"); snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u", ntohl(header.hdr_version), ntohl(header.hdr_entries)); - if (ntohl(header.hdr_entries) < keep_auto) + if (ntohl(header.hdr_entries) < unpack_limit) do_keep = 0; else do_keep = 1; @@ -523,7 +523,7 @@ static int get_pack(int xd[2]) *av++ = "-v"; if (use_thin_pack) *av++ = "--fix-thin"; - if (keep_pack > 1 || keep_auto) { + if (keep_pack > 1 || unpack_limit) { int s = sprintf(keep_arg, "--keep=fetch-pack %d on ", getpid()); if (gethostname(keep_arg + s, sizeof(keep_arg) - s)) @@ -642,6 +642,16 @@ static int remove_duplicates(int nr_heads, char **heads) return dst; } +static int fetch_pack_config(const char *var, const char *value) +{ + if (strcmp(var, "fetch.unpacklimit") == 0) { + unpack_limit = git_config_int(var, value); + return 0; + } + + return git_default_config(var, value); +} + static struct lock_file lock; int main(int argc, char **argv) @@ -653,6 +663,8 @@ int main(int argc, char **argv) struct stat st; setup_git_directory(); + setup_ident(); + git_config(fetch_pack_config); nr_heads = 0; heads = NULL; @@ -674,16 +686,7 @@ int main(int argc, char **argv) } if (!strcmp("--keep", arg) || !strcmp("-k", arg)) { keep_pack++; - continue; - } - if (!strcmp("--keep-auto", arg)) { - keep_auto = 100; - continue; - } - if (!strncmp("--keep-auto=", arg, 12)) { - keep_auto = strtoul(arg + 12, NULL, 0); - if (keep_auto < 20) - keep_auto = 20; + unpack_limit = 0; continue; } if (!strcmp("--thin", arg)) { diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index ef78df67ea..7fd651b1c4 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -97,7 +97,8 @@ pull_to_client () { ( mkdir client && cd client && - git-init 2>> log2.txt + git-init 2>> log2.txt && + git repo-config fetch.unpacklimit 0 ) add A1 From e28714c527339a477fca226765163b9361d94285 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 24 Jan 2007 17:02:15 -0800 Subject: [PATCH 14/14] Consolidate {receive,fetch}.unpackLimit This allows transfer.unpackLimit to specify what these two configuration variables want to set. We would probably want to deprecate the two separate variables, as I do not see much point in specifying them independently. Signed-off-by: Junio C Hamano --- Documentation/config.txt | 5 +++++ fetch-pack.c | 14 +++++++++++++- receive-pack.c | 24 ++++++++++++++++-------- t/t5500-fetch-pack.sh | 2 +- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 383ff29f82..8086d75368 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -488,3 +488,8 @@ receive.denyNonFastForwards:: even if that push is forced. This configuration variable is set when initializing a shared repository. +transfer.unpackLimit:: + When `fetch.unpackLimit` or `receive.unpackLimit` are + not set, the value of this variable is used instead. + + diff --git a/fetch-pack.c b/fetch-pack.c index fc0534ce03..83a1d7b319 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -8,6 +8,8 @@ #include "sideband.h" static int keep_pack; +static int transfer_unpack_limit = -1; +static int fetch_unpack_limit = -1; static int unpack_limit = 100; static int quiet; static int verbose; @@ -645,7 +647,12 @@ static int remove_duplicates(int nr_heads, char **heads) static int fetch_pack_config(const char *var, const char *value) { if (strcmp(var, "fetch.unpacklimit") == 0) { - unpack_limit = git_config_int(var, value); + fetch_unpack_limit = git_config_int(var, value); + return 0; + } + + if (strcmp(var, "transfer.unpacklimit") == 0) { + transfer_unpack_limit = git_config_int(var, value); return 0; } @@ -666,6 +673,11 @@ int main(int argc, char **argv) setup_ident(); git_config(fetch_pack_config); + if (0 <= transfer_unpack_limit) + unpack_limit = transfer_unpack_limit; + else if (0 <= fetch_unpack_limit) + unpack_limit = fetch_unpack_limit; + nr_heads = 0; heads = NULL; for (i = 1; i < argc; i++) { diff --git a/receive-pack.c b/receive-pack.c index b3a4552692..8b59b3227e 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -10,6 +10,8 @@ static const char receive_pack_usage[] = "git-receive-pack "; static int deny_non_fast_forwards = 0; +static int receive_unpack_limit = -1; +static int transfer_unpack_limit = -1; static int unpack_limit = 100; static int report_status; @@ -18,21 +20,22 @@ static int capabilities_sent; static int receive_pack_config(const char *var, const char *value) { - git_default_config(var, value); - - if (strcmp(var, "receive.denynonfastforwards") == 0) - { + if (strcmp(var, "receive.denynonfastforwards") == 0) { deny_non_fast_forwards = git_config_bool(var, value); return 0; } - if (strcmp(var, "receive.unpacklimit") == 0) - { - unpack_limit = git_config_int(var, value); + if (strcmp(var, "receive.unpacklimit") == 0) { + receive_unpack_limit = git_config_int(var, value); return 0; } - return 0; + if (strcmp(var, "transfer.unpacklimit") == 0) { + transfer_unpack_limit = git_config_int(var, value); + return 0; + } + + return git_default_config(var, value); } static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) @@ -431,6 +434,11 @@ int main(int argc, char **argv) ignore_missing_committer_name(); git_config(receive_pack_config); + if (0 <= transfer_unpack_limit) + unpack_limit = transfer_unpack_limit; + else if (0 <= receive_unpack_limit) + unpack_limit = receive_unpack_limit; + write_head_info(); /* EOF */ diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 7fd651b1c4..058cce0775 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -98,7 +98,7 @@ pull_to_client () { mkdir client && cd client && git-init 2>> log2.txt && - git repo-config fetch.unpacklimit 0 + git repo-config transfer.unpacklimit 0 ) add A1