diff options
-rw-r--r-- | Documentation/config.txt | 21 | ||||
-rw-r--r-- | Documentation/git-cvsexportcommit.txt | 8 | ||||
-rw-r--r-- | Documentation/git-tar-tree.txt | 15 | ||||
-rw-r--r-- | Makefile | 30 | ||||
-rw-r--r-- | builtin-read-tree.c | 4 | ||||
-rw-r--r-- | builtin-show-branch.c | 2 | ||||
-rw-r--r-- | builtin-tar-tree.c | 21 | ||||
-rw-r--r-- | cache.h | 1 | ||||
-rw-r--r-- | config.c | 5 | ||||
-rw-r--r-- | contrib/emacs/git.el | 31 | ||||
-rw-r--r-- | diff.c | 28 | ||||
-rw-r--r-- | diff.h | 11 | ||||
-rw-r--r-- | environment.c | 1 | ||||
-rwxr-xr-x | git-am.sh | 12 | ||||
-rwxr-xr-x | git-cvsexportcommit.perl | 50 | ||||
-rwxr-xr-x | git-fetch.sh | 6 | ||||
-rwxr-xr-x | git-merge.sh | 17 | ||||
-rwxr-xr-x | git-pull.sh | 3 | ||||
-rwxr-xr-x | git-quiltimport.sh | 2 | ||||
-rwxr-xr-x | git-rebase.sh | 9 | ||||
-rwxr-xr-x | git-resolve.sh | 7 | ||||
-rwxr-xr-x | git-svn.perl | 23 | ||||
-rw-r--r-- | log-tree.c | 5 | ||||
-rw-r--r-- | pack-objects.c | 13 | ||||
-rw-r--r-- | sha1_file.c | 106 | ||||
-rwxr-xr-x | t/t6004-rev-list-path-optim.sh | 19 | ||||
-rw-r--r-- | unpack-objects.c | 5 | ||||
-rw-r--r-- | upload-pack.c | 2 |
28 files changed, 372 insertions, 85 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt index 0b434c1f19..465eb13e76 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -97,6 +97,12 @@ core.compression:: compression, and 1..9 are various speed/size tradeoffs, 9 being slowest. +core.legacyheaders:: + A boolean which enables the legacy object header format in case + you want to interoperate with old clients accessing the object + database directly (where the "http://" and "rsync://" protocols + count as direct access). + alias.*:: Command aliases for the gitlink:git[1] command wrapper - e.g. after defining "alias.last = cat-file commit HEAD", the invocation @@ -193,6 +199,10 @@ merge.summary:: Whether to include summaries of merged commits in newly created merge commit messages. False by default. +pack.window:: + The size of the window used by gitlink:git-pack-objects[1] when no + window size is given on the command line. Defaults to 10. + pull.octopus:: The default merge strategy to use when pulling multiple branches at once. @@ -208,6 +218,17 @@ showbranch.default:: The default set of branches for gitlink:git-show-branch[1]. See gitlink:git-show-branch[1]. +tar.umask:: + By default, git-link:git-tar-tree[1] sets file and directories modes + to 0666 or 0777. While this is both useful and acceptable for projects + such as the Linux Kernel, it might be excessive for other projects. + With this variable, it becomes possible to tell + git-link:git-tar-tree[1] to apply a specific umask to the modes above. + The special value "user" indicates that the user's current umask will + be used. This should be enough for most projects, as it will lead to + the same permissions as git-link:git-checkout[1] would use. The default + value remains 0, which means world read-write. + user.email:: Your email address to be recorded in any newly created commits. Can be overridden by the 'GIT_AUTHOR_EMAIL' and 'GIT_COMMITTER_EMAIL' diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt index 27ac72d98f..092d0d6730 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.txt @@ -8,7 +8,7 @@ git-cvsexportcommit - Export a commit to a CVS checkout SYNOPSIS -------- -'git-cvsexportcommit' [-h] [-v] [-c] [-p] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID +'git-cvsexportcommit' [-h] [-v] [-c] [-p] [-a] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID DESCRIPTION @@ -36,9 +36,13 @@ OPTIONS commit if any hunks fail to apply or there were other problems. -p:: - Be pedantic (paranoid) when applying patches. Invokes patch with + Be pedantic (paranoid) when applying patches. Invokes patch with --fuzz=0 +-a:: + Add authorship information. Adds Author line, and Committer (if + different from Author) to the message. + -f:: Force the merge even if the files are not up to date. diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt index f2675c4193..7a99acf2ec 100644 --- a/Documentation/git-tar-tree.txt +++ b/Documentation/git-tar-tree.txt @@ -37,7 +37,20 @@ OPTIONS Instead of making a tar archive from local repository, retrieve a tar archive from a remote repository. -Examples +CONFIGURATION +------------- +By default, file and directories modes are set to 0666 or 0777. It is +possible to change this by setting the "umask" variable in the +repository configuration as follows : + +[tar] + umask = 002 ;# group friendly + +The special umask value "user" indicates that the user's current umask +will be used instead. The default value remains 0, which means world +readable/writable files and directories. + +EXAMPLES -------- git tar-tree HEAD junk | (cd /var/tmp/ && tar xf -):: @@ -37,6 +37,18 @@ all: # tests. These tests take up a significant amount of the total test time # but are not needed unless you plan to talk to SVN repos. # +# Define NO_FINK if you are building on Darwin/Mac OS X, have Fink +# installed in /sw, but don't want GIT to link against any libraries +# installed there. If defined you may specify your own (or Fink's) +# include directories and library directories by defining CFLAGS +# and LDFLAGS appropriately. +# +# Define NO_DARWIN_PORTS if you are building on Darwin/Mac OS X, +# have DarwinPorts installed in /opt/local, but don't want GIT to +# link against any libraries installed there. If defined you may +# specify your own (or DarwinPort's) include directories and +# library directories by defining CFLAGS and LDFLAGS appropriately. +# # Define PPC_SHA1 environment variable when running make to make use of # a bundled SHA1 routine optimized for PowerPC. # @@ -254,15 +266,17 @@ ifeq ($(uname_S),Darwin) NEEDS_SSL_WITH_CRYPTO = YesPlease NEEDS_LIBICONV = YesPlease NO_STRLCPY = YesPlease - ## fink - ifeq ($(shell test -d /sw/lib && echo y),y) - ALL_CFLAGS += -I/sw/include - ALL_LDFLAGS += -L/sw/lib + ifndef NO_FINK + ifeq ($(shell test -d /sw/lib && echo y),y) + ALL_CFLAGS += -I/sw/include + ALL_LDFLAGS += -L/sw/lib + endif endif - ## darwinports - ifeq ($(shell test -d /opt/local/lib && echo y),y) - ALL_CFLAGS += -I/opt/local/include - ALL_LDFLAGS += -L/opt/local/lib + ifndef NO_DARWIN_PORTS + ifeq ($(shell test -d /opt/local/lib && echo y),y) + ALL_CFLAGS += -I/opt/local/include + ALL_LDFLAGS += -L/opt/local/lib + endif endif endif ifeq ($(uname_S),SunOS) diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 6df5d7c5cb..122b6f130b 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -507,7 +507,7 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old) } merge->ce_flags &= ~htons(CE_STAGEMASK); - add_cache_entry(merge, ADD_CACHE_OK_TO_ADD); + add_cache_entry(merge, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); return 1; } @@ -518,7 +518,7 @@ static int deleted_entry(struct cache_entry *ce, struct cache_entry *old) else verify_absent(ce->name, "removed"); ce->ce_mode = 0; - add_cache_entry(ce, ADD_CACHE_OK_TO_ADD); + add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); invalidate_ce_path(ce); return 1; } diff --git a/builtin-show-branch.c b/builtin-show-branch.c index 3d240ca435..82f75b72de 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -89,6 +89,8 @@ static int name_first_parent_chain(struct commit *c) name_parent(c, p); i++; } + else + break; c = p; } return i; diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index f2e48aae2a..e5aaded820 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -20,6 +20,7 @@ static char block[BLOCKSIZE]; static unsigned long offset; static time_t archive_time; +static int tar_umask; /* tries hard to write, either succeeds or dies in the attempt */ static void reliable_write(const void *data, unsigned long size) @@ -188,13 +189,13 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, } else { if (S_ISDIR(mode)) { *header.typeflag = TYPEFLAG_DIR; - mode |= 0777; + mode = (mode | 0777) & ~tar_umask; } else if (S_ISLNK(mode)) { *header.typeflag = TYPEFLAG_LNK; mode |= 0777; } else if (S_ISREG(mode)) { *header.typeflag = TYPEFLAG_REG; - mode |= (mode & 0100) ? 0777 : 0666; + mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask; } else { error("unsupported file mode: 0%o (SHA1: %s)", mode, sha1_to_hex(sha1)); @@ -293,6 +294,20 @@ static void traverse_tree(struct tree_desc *tree, struct strbuf *path) } } +int git_tar_config(const char *var, const char *value) +{ + if (!strcmp(var, "tar.umask")) { + if (!strcmp(value, "user")) { + tar_umask = umask(0); + umask(tar_umask); + } else { + tar_umask = git_config_int(var, value); + } + return 0; + } + return git_default_config(var, value); +} + static int generate_tar(int argc, const char **argv, char** envp) { unsigned char sha1[20], tree_sha1[20]; @@ -305,7 +320,7 @@ static int generate_tar(int argc, const char **argv, char** envp) current_path.len = current_path.eof = 0; setup_git_directory(); - git_config(git_default_config); + git_config(git_tar_config); switch (argc) { case 3: @@ -176,6 +176,7 @@ extern int commit_lock_file(struct lock_file *); extern void rollback_lock_file(struct lock_file *); /* Environment bits from configuration mechanism */ +extern int use_legacy_headers; extern int trust_executable_bit; extern int assume_unchanged; extern int prefer_symlink_refs; @@ -279,6 +279,11 @@ int git_default_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.legacyheaders")) { + use_legacy_headers = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "core.compression")) { int level = git_config_int(var, value); if (level == -1) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 34c995046d..68de9be0c7 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -55,7 +55,8 @@ ;;;; ------------------------------------------------------------ (defgroup git nil - "Git user interface") + "A user interface for the git versioning system." + :group 'tools) (defcustom git-committer-name nil "User name to use for commits. @@ -83,6 +84,12 @@ then to `add-log-mailing-address' and then to `user-mail-address'." :group 'git :type 'boolean) +(defcustom git-reuse-status-buffer t + "Whether `git-status' should try to reuse an existing buffer +if there is already one that displays the same directory." + :group 'git + :type 'boolean) + (defcustom git-per-dir-ignore-file ".gitignore" "Name of the per-directory ignore file." :group 'git @@ -258,7 +265,7 @@ and returns the process output as a string." (set-buffer (find-file-noselect ignore-name)) (goto-char (point-max)) (unless (zerop (current-column)) (insert "\n")) - (insert name "\n") + (insert "/" name "\n") (sort-lines nil (point-min) (point-max)) (save-buffer)) (when created @@ -584,6 +591,8 @@ and returns the process output as a string." (condition-case nil (delete-file ".git/MERGE_HEAD") (error nil)) (with-current-buffer buffer (erase-buffer)) (git-set-files-state files 'uptodate) + (when (file-directory-p ".git/rr-cache") + (git-run-command nil nil "rerere")) (git-refresh-files) (git-refresh-ewoc-hf git-status) (message "Committed %s." commit)) @@ -1001,12 +1010,28 @@ Commands: (set (make-local-variable 'list-buffers-directory) default-directory) (run-hooks 'git-status-mode-hook))) +(defun git-find-status-buffer (dir) + "Find the git status buffer handling a specified directory." + (let ((list (buffer-list)) + (fulldir (expand-file-name dir)) + found) + (while (and list (not found)) + (let ((buffer (car list))) + (with-current-buffer buffer + (when (and list-buffers-directory + (string-equal fulldir (expand-file-name list-buffers-directory)) + (string-match "\\*git-status\\*$" (buffer-name buffer))) + (setq found buffer)))) + (setq list (cdr list))) + found)) + (defun git-status (dir) "Entry point into git-status mode." (interactive "DSelect directory: ") (setq dir (git-get-top-dir dir)) (if (file-directory-p (concat (file-name-as-directory dir) ".git")) - (let ((buffer (create-file-buffer (expand-file-name "*git-status*" dir)))) + (let ((buffer (or (and git-reuse-status-buffer (git-find-status-buffer dir)) + (create-file-buffer (expand-file-name "*git-status*" dir))))) (switch-to-buffer buffer) (cd dir) (git-status-mode) @@ -17,15 +17,6 @@ static int diff_detect_rename_default = 0; static int diff_rename_limit_default = -1; static int diff_use_color_default = 0; -enum color_diff { - DIFF_RESET = 0, - DIFF_PLAIN = 1, - DIFF_METAINFO = 2, - DIFF_FRAGINFO = 3, - DIFF_FILE_OLD = 4, - DIFF_FILE_NEW = 5, -}; - /* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ static char diff_colors[][24] = { "\033[m", /* reset */ @@ -33,7 +24,8 @@ static char diff_colors[][24] = { "\033[1m", /* bold */ "\033[36m", /* cyan */ "\033[31m", /* red */ - "\033[32m" /* green */ + "\033[32m", /* green */ + "\033[33m" /* yellow */ }; static int parse_diff_color_slot(const char *var, int ofs) @@ -48,6 +40,8 @@ static int parse_diff_color_slot(const char *var, int ofs) return DIFF_FILE_OLD; if (!strcasecmp(var+ofs, "new")) return DIFF_FILE_NEW; + if (!strcasecmp(var+ofs, "commit")) + return DIFF_COMMIT; die("bad config variable '%s'", var); } @@ -370,7 +364,7 @@ struct emit_callback { const char **label_path; }; -static inline const char *get_color(int diff_use_color, enum color_diff ix) +const char *diff_get_color(int diff_use_color, enum color_diff ix) { if (diff_use_color) return diff_colors[ix]; @@ -381,8 +375,8 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) { int i; struct emit_callback *ecbdata = priv; - const char *set = get_color(ecbdata->color_diff, DIFF_METAINFO); - const char *reset = get_color(ecbdata->color_diff, DIFF_RESET); + const char *set = diff_get_color(ecbdata->color_diff, DIFF_METAINFO); + const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET); if (ecbdata->label_path[0]) { printf("%s--- %s%s\n", set, ecbdata->label_path[0], reset); @@ -397,7 +391,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) ; if (2 <= i && i < len && line[i] == ' ') { ecbdata->nparents = i - 1; - set = get_color(ecbdata->color_diff, DIFF_FRAGINFO); + set = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO); } else if (len < ecbdata->nparents) set = reset; @@ -410,7 +404,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) else if (line[i] == '+') color = DIFF_FILE_NEW; } - set = get_color(ecbdata->color_diff, color); + set = diff_get_color(ecbdata->color_diff, color); } if (len > 0 && line[len-1] == '\n') len--; @@ -767,8 +761,8 @@ static void builtin_diff(const char *name_a, mmfile_t mf1, mf2; const char *lbl[2]; char *a_one, *b_two; - const char *set = get_color(o->color_diff, DIFF_METAINFO); - const char *reset = get_color(o->color_diff, DIFF_RESET); + const char *set = diff_get_color(o->color_diff, DIFF_METAINFO); + const char *reset = diff_get_color(o->color_diff, DIFF_RESET); a_one = quote_two("a/", name_a); b_two = quote_two("b/", name_b); @@ -69,6 +69,17 @@ struct diff_options { add_remove_fn_t add_remove; }; +enum color_diff { + DIFF_RESET = 0, + DIFF_PLAIN = 1, + DIFF_METAINFO = 2, + DIFF_FRAGINFO = 3, + DIFF_FILE_OLD = 4, + DIFF_FILE_NEW = 5, + DIFF_COMMIT = 6, +}; +const char *diff_get_color(int diff_use_color, enum color_diff ix); + extern const char mime_boundary_leader[]; extern void diff_tree_setup_paths(const char **paths, struct diff_options *); diff --git a/environment.c b/environment.c index 97d42b172b..42f39d657e 100644 --- a/environment.c +++ b/environment.c @@ -11,6 +11,7 @@ char git_default_email[MAX_GITNAME]; char git_default_name[MAX_GITNAME]; +int use_legacy_headers = 1; int trust_executable_bit = 1; int assume_unchanged = 0; int prefer_symlink_refs = 0; @@ -91,6 +91,7 @@ fall_back_3way () { } prec=4 +rloga=am dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary= ws= resolvemsg= while case "$#" in 0) break;; esac @@ -130,6 +131,9 @@ do --resolvemsg=*) resolvemsg=$(echo "$1" | sed -e "s/^--resolvemsg=//"); shift ;; + --reflog-action=*) + rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`; shift ;; + --) shift; break ;; -*) @@ -152,8 +156,10 @@ fi if test -d "$dotest" then - test ",$#," = ",0," || - die "previous dotest directory $dotest still exists but mbox given." + if test ",$#," != ",0," || ! tty -s + then + die "previous dotest directory $dotest still exists but mbox given." + fi resume=yes else # Make sure we are not given --skip nor --resolved @@ -413,7 +419,7 @@ do parent=$(git-rev-parse --verify HEAD) && commit=$(git-commit-tree $tree -p $parent <"$dotest/final-commit") && echo Committed: $commit && - git-update-ref -m "am: $SUBJECT" HEAD $commit $parent || + git-update-ref -m "$rloga: $SUBJECT" HEAD $commit $parent || stop_here $this if test -x "$GIT_DIR"/hooks/post-applypatch diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index 5d13a54194..99b3dc392a 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -16,9 +16,9 @@ unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){ die "GIT_DIR is not defined or is unreadable"; } -our ($opt_h, $opt_p, $opt_v, $opt_c, $opt_f, $opt_m ); +our ($opt_h, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m ); -getopts('hpvcfm:'); +getopts('hpvcfam:'); $opt_h && usage(); @@ -29,7 +29,6 @@ our ($tmpdir, $tmpdirname) = tempdir('git-cvsapplycommit-XXXXXX', TMPDIR => 1, CLEANUP => 1); -print Dumper(@ARGV); # resolve target commit my $commit; $commit = pop @ARGV; @@ -53,12 +52,32 @@ if (@ARGV) { # find parents from the commit itself my @commit = safe_pipe_capture('git-cat-file', 'commit', $commit); my @parents; -foreach my $p (@commit) { - if ($p =~ m/^$/) { # end of commit headers, we're done - last; +my $committer; +my $author; +my $stage = 'headers'; # headers, msg +my $title; +my $msg = ''; + +foreach my $line (@commit) { + chomp $line; + if ($stage eq 'headers' && $line eq '') { + $stage = 'msg'; + next; } - if ($p =~ m/^parent (\w{40})$/) { # found a parent - push @parents, $1; + + if ($stage eq 'headers') { + if ($line =~ m/^parent (\w{40})$/) { # found a parent + push @parents, $1; + } elsif ($line =~ m/^author (.+) \d+ \+\d+$/) { + $author = $1; + } elsif ($line =~ m/^committer (.+) \d+ \+\d+$/) { + $committer = $1; + } + } else { + $msg .= $line . "\n"; + unless ($title) { + $title = $line; + } } } @@ -84,12 +103,18 @@ $opt_v && print "Applying to CVS commit $commit from parent $parent\n"; # grab the commit message open(MSG, ">.msg") or die "Cannot open .msg for writing"; -print MSG $opt_m; +if ($opt_m) { + print MSG $opt_m; +} +print MSG $msg; +if ($opt_a) { + print MSG "\n\nAuthor: $author\n"; + if ($author ne $committer) { + print MSG "Committer: $committer\n"; + } +} close MSG; -`git-cat-file commit $commit | sed -e '1,/^\$/d' >> .msg`; -$? && die "Error extracting the commit message"; - my (@afiles, @dfiles, @mfiles, @dirs); my @files = safe_pipe_capture('git-diff-tree', '-r', $parent, $commit); #print @files; @@ -233,6 +258,7 @@ foreach my $f (@dfiles) { } print "Commit to CVS\n"; +print "Patch: $title\n"; my $commitfiles = join(' ', @afiles, @mfiles, @dfiles); my $cmd = "cvs commit -F .msg $commitfiles"; diff --git a/git-fetch.sh b/git-fetch.sh index ee99280a2a..f7167abdf0 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -20,6 +20,7 @@ verbose= update_head_ok= exec= upload_pack= +keep=--thin while case "$#" in 0) break ;; esac do case "$1" in @@ -69,7 +70,8 @@ case "$#" in 0) test -f "$GIT_DIR/branches/origin" || test -f "$GIT_DIR/remotes/origin" || - die "Where do you want to fetch from today?" + git-repo-config --get remote.origin.url >/dev/null || + die "Where do you want to fetch from today?" set origin ;; esac @@ -347,7 +349,7 @@ fetch_main () { ( : subshell because we muck with IFS IFS=" $LF" ( - git-fetch-pack $exec $keep --thin "$remote" $rref || echo failed "$remote" + git-fetch-pack $exec $keep "$remote" $rref || echo failed "$remote" ) | while read sha1 remote_name do diff --git a/git-merge.sh b/git-merge.sh index 24e3b507ef..a9cfafb1df 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -58,7 +58,13 @@ squash_message () { } finish () { - test '' = "$2" || echo "$2" + if test '' = "$2" + then + rlogm="$rloga" + else + echo "$2" + rlogm="$rloga: $2" + fi case "$squash" in t) echo "Squash commit -- not updating HEAD" @@ -70,7 +76,7 @@ finish () { echo "No merge message -- not updating HEAD" ;; *) - git-update-ref HEAD "$1" "$head" || exit 1 + git-update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1 ;; esac ;; @@ -88,6 +94,7 @@ finish () { esac } +rloga= while case "$#" in 0) break ;; esac do case "$1" in @@ -117,6 +124,9 @@ do die "available strategies are: $all_strategies" ;; esac ;; + --reflog-action=*) + rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'` + ;; -*) usage ;; *) break ;; esac @@ -131,6 +141,7 @@ shift # All the rest are remote heads test "$#" = 0 && usage ;# we need at least one remote head. +test "$rloga" = '' && rloga="merge: $@" remoteheads= for remote @@ -316,7 +327,7 @@ if test '' != "$result_tree" then parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /') result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit - finish "$result_commit" "Merge $result_commit, made by $wt_strategy." + finish "$result_commit" "Merge made by $wt_strategy." dropsave exit 0 fi diff --git a/git-pull.sh b/git-pull.sh index d337bf4da3..f380437997 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -102,5 +102,6 @@ case "$strategy_args" in esac merge_name=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD") || exit -git-merge $no_summary $no_commit $squash $strategy_args \ +git-merge "--reflog-action=pull $*" \ + $no_summary $no_commit $squash $strategy_args \ "$merge_name" HEAD $merge_head diff --git a/git-quiltimport.sh b/git-quiltimport.sh index 364baff806..10135da3ac 100755 --- a/git-quiltimport.sh +++ b/git-quiltimport.sh @@ -112,7 +112,7 @@ for patch_name in $(cat "$QUILT_PATCHES/series" | grep -v '^#'); do git-apply --index -C1 "$tmp_patch" && tree=$(git-write-tree) && commit=$((echo "$SUBJECT"; echo; cat "$tmp_msg") | git-commit-tree $tree -p $commit) && - git-update-ref HEAD $commit || exit 4 + git-update-ref -m "quiltimport: $patch_name" HEAD $commit || exit 4 fi done rm -rf $tmp_dir || exit 5 diff --git a/git-rebase.sh b/git-rebase.sh index 1b9e986926..29028dd5fc 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -131,7 +131,8 @@ do finish_rb_merge exit fi - git am --resolved --3way --resolvemsg="$RESOLVEMSG" + git am --resolved --3way --resolvemsg="$RESOLVEMSG" \ + --reflog-action=rebase exit ;; --skip) @@ -150,7 +151,8 @@ do finish_rb_merge exit fi - git am -3 --skip --resolvemsg="$RESOLVEMSG" + git am -3 --skip --resolvemsg="$RESOLVEMSG" \ + --reflog-action=rebase exit ;; --abort) @@ -288,7 +290,8 @@ fi if test -z "$do_merge" then git-format-patch -k --stdout --full-index "$upstream"..ORIG_HEAD | - git am --binary -3 -k --resolvemsg="$RESOLVEMSG" + git am --binary -3 -k --resolvemsg="$RESOLVEMSG" \ + --reflog-action=rebase exit $? fi diff --git a/git-resolve.sh b/git-resolve.sh index 1c7aaefa25..a7bc680d90 100755 --- a/git-resolve.sh +++ b/git-resolve.sh @@ -15,6 +15,7 @@ dropheads() { head=$(git-rev-parse --verify "$1"^0) && merge=$(git-rev-parse --verify "$2"^0) && +merge_name="$2" && merge_msg="$3" || usage # @@ -43,7 +44,8 @@ case "$common" in "$head") echo "Updating from $head to $merge" git-read-tree -u -m $head $merge || exit 1 - git-update-ref HEAD "$merge" "$head" + git-update-ref -m "resolve $merge_name: Fast forward" \ + HEAD "$merge" "$head" git-diff-tree -p $head $merge | git-apply --stat dropheads exit 0 @@ -100,6 +102,7 @@ if [ $? -ne 0 ]; then fi result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree -p $head -p $merge) echo "Committed merge $result_commit" -git-update-ref HEAD "$result_commit" "$head" +git-update-ref -m "resolve $merge_name: In-index merge" \ + HEAD "$result_commit" "$head" git-diff-tree -p $head $result_commit | git-apply --stat dropheads diff --git a/git-svn.perl b/git-svn.perl index 89ad840dbf..6453771f9c 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -2709,6 +2709,12 @@ sub libsvn_fetch { } else { die "Unrecognized action: $m, ($f r$rev)\n"; } + } elsif ($t == $SVN::Node::dir && $m =~ /^[AR]$/) { + my @traversed = (); + libsvn_traverse($gui, '', $f, $rev, \@traversed); + foreach (@traversed) { + push @amr, [ $m, $_ ] + } } $pool->clear; } @@ -2778,7 +2784,7 @@ sub libsvn_parse_revision { } sub libsvn_traverse { - my ($gui, $pfx, $path, $rev) = @_; + my ($gui, $pfx, $path, $rev, $files) = @_; my $cwd = "$pfx/$path"; my $pool = SVN::Pool->new; $cwd =~ s#^/+##g; @@ -2786,10 +2792,15 @@ sub libsvn_traverse { foreach my $d (keys %$dirent) { my $t = $dirent->{$d}->kind; if ($t == $SVN::Node::dir) { - libsvn_traverse($gui, $cwd, $d, $rev); + libsvn_traverse($gui, $cwd, $d, $rev, $files); } elsif ($t == $SVN::Node::file) { - print "\tA\t$cwd/$d\n" unless $_q; - libsvn_get_file($gui, "$cwd/$d", $rev); + my $file = "$cwd/$d"; + if (defined $files) { + push @$files, $file; + } else { + print "\tA\t$file\n" unless $_q; + libsvn_get_file($gui, $file, $rev); + } } } $pool->clear; @@ -2913,9 +2924,7 @@ sub libsvn_new_tree { } my ($paths, $rev, $author, $date, $msg) = @_; open my $gui, '| git-update-index -z --index-info' or croak $!; - my $pool = SVN::Pool->new; - libsvn_traverse($gui, '', $SVN_PATH, $rev, $pool); - $pool->clear; + libsvn_traverse($gui, '', $SVN_PATH, $rev); close $gui or croak $?; return libsvn_log_entry($rev, $author, $date, $msg); } diff --git a/log-tree.c b/log-tree.c index 9d8d46fa00..3a6c84dab5 100644 --- a/log-tree.c +++ b/log-tree.c @@ -129,7 +129,8 @@ void show_log(struct rev_info *opt, const char *sep) opt->diffopt.stat_sep = buffer; } } else { - printf("%s%s", + printf("%s%s%s", + diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT), opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ", diff_unique_abbrev(commit->object.sha1, abbrev_commit)); if (opt->parents) @@ -138,6 +139,8 @@ void show_log(struct rev_info *opt, const char *sep) printf(" (from %s)", diff_unique_abbrev(parent->object.sha1, abbrev_commit)); + printf("%s", + diff_get_color(opt->diffopt.color_diff, DIFF_RESET)); putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n'); } diff --git a/pack-objects.c b/pack-objects.c index 04a48b925b..861c7f08ff 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -63,6 +63,7 @@ static const char *base_name; static unsigned char pack_file_sha1[20]; static int progress = 1; static volatile sig_atomic_t progress_update = 0; +static int window = 10; /* * The object names in objects array are hashed with this hashtable, @@ -1216,16 +1217,26 @@ static void setup_progress_signal(void) setitimer(ITIMER_REAL, &v, NULL); } +static int git_pack_config(const char *k, const char *v) +{ + if(!strcmp(k, "pack.window")) { + window = git_config_int(k, v); + return 0; + } + return git_default_config(k, v); +} + int main(int argc, char **argv) { SHA_CTX ctx; char line[40 + 1 + PATH_MAX + 2]; - int window = 10, depth = 10, pack_to_stdout = 0; + int depth = 10, pack_to_stdout = 0; struct object_entry **list; int num_preferred_base = 0; int i; setup_git_directory(); + git_config(git_pack_config); progress = isatty(2); for (i = 1; i < argc; i++) { diff --git a/sha1_file.c b/sha1_file.c index e666aec502..43bc2ea0cf 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -684,26 +684,74 @@ static void *map_sha1_file_internal(const unsigned char *sha1, return map; } -static int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void *buffer, unsigned long size) +static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz) { + unsigned char c; + unsigned int word, bits; + unsigned long size; + static const char *typename[8] = { + NULL, /* OBJ_EXT */ + "commit", "tree", "blob", "tag", + NULL, NULL, NULL + }; + const char *type; + /* Get the data stream */ memset(stream, 0, sizeof(*stream)); stream->next_in = map; stream->avail_in = mapsize; stream->next_out = buffer; - stream->avail_out = size; + stream->avail_out = bufsiz; + + /* + * Is it a zlib-compressed buffer? If so, the first byte + * must be 0x78 (15-bit window size, deflated), and the + * first 16-bit word is evenly divisible by 31 + */ + word = (map[0] << 8) + map[1]; + if (map[0] == 0x78 && !(word % 31)) { + inflateInit(stream); + return inflate(stream, 0); + } + + c = *map++; + mapsize--; + type = typename[(c >> 4) & 7]; + if (!type) + return -1; + + bits = 4; + size = c & 0xf; + while ((c & 0x80)) { + if (bits >= 8*sizeof(long)) + return -1; + c = *map++; + size += (c & 0x7f) << bits; + bits += 7; + mapsize--; + } + /* Set up the stream for the rest.. */ + stream->next_in = map; + stream->avail_in = mapsize; inflateInit(stream); - return inflate(stream, 0); + + /* And generate the fake traditional header */ + stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", type, size); + return 0; } static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size) { int bytes = strlen(buffer) + 1; unsigned char *buf = xmalloc(1+size); + unsigned long n; - memcpy(buf, (char *) buffer + bytes, stream->total_out - bytes); - bytes = stream->total_out - bytes; + n = stream->total_out - bytes; + if (n > size) + n = size; + memcpy(buf, (char *) buffer + bytes, n); + bytes = n; if (bytes < size) { stream->next_out = buf + bytes; stream->avail_out = size - bytes; @@ -1412,6 +1460,49 @@ static int write_buffer(int fd, const void *buf, size_t len) return 0; } +static int write_binary_header(unsigned char *hdr, enum object_type type, unsigned long len) +{ + int hdr_len; + unsigned char c; + + c = (type << 4) | (len & 15); + len >>= 4; + hdr_len = 1; + while (len) { + *hdr++ = c | 0x80; + hdr_len++; + c = (len & 0x7f); + len >>= 7; + } + *hdr = c; + return hdr_len; +} + +static void setup_object_header(z_stream *stream, const char *type, unsigned long len) +{ + int obj_type, hdr; + + if (use_legacy_headers) { + while (deflate(stream, 0) == Z_OK) + /* nothing */; + return; + } + if (!strcmp(type, blob_type)) + obj_type = OBJ_BLOB; + else if (!strcmp(type, tree_type)) + obj_type = OBJ_TREE; + else if (!strcmp(type, commit_type)) + obj_type = OBJ_COMMIT; + else if (!strcmp(type, tag_type)) + obj_type = OBJ_TAG; + else + die("trying to generate bogus object of type '%s'", type); + hdr = write_binary_header(stream->next_out, obj_type, len); + stream->total_out = hdr; + stream->next_out += hdr; + stream->avail_out -= hdr; +} + int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1) { int size; @@ -1457,7 +1548,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha /* Set it up */ memset(&stream, 0, sizeof(stream)); deflateInit(&stream, zlib_compression_level); - size = deflateBound(&stream, len+hdrlen); + size = 8 + deflateBound(&stream, len+hdrlen); compressed = xmalloc(size); /* Compress it */ @@ -1467,8 +1558,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha /* First header.. */ stream.next_in = hdr; stream.avail_in = hdrlen; - while (deflate(&stream, 0) == Z_OK) - /* nothing */; + setup_object_header(&stream, type, len); /* Then the data itself.. */ stream.next_in = buf; diff --git a/t/t6004-rev-list-path-optim.sh b/t/t6004-rev-list-path-optim.sh new file mode 100755 index 0000000000..5182dbb158 --- /dev/null +++ b/t/t6004-rev-list-path-optim.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +test_description='git-rev-list trivial path optimization test' + +. ./test-lib.sh + +test_expect_success setup ' +echo Hello > a && +git add a && +git commit -m "Initial commit" a +' + +test_expect_success path-optimization ' + commit=$(echo "Unchanged tree" | git-commit-tree "HEAD^{tree}" -p HEAD) && + test $(git-rev-list $commit | wc -l) = 2 && + test $(git-rev-list $commit -- . | wc -l) = 1 +' + +test_done diff --git a/unpack-objects.c b/unpack-objects.c index 3b824b04a2..48c1ee7968 100644 --- a/unpack-objects.c +++ b/unpack-objects.c @@ -241,11 +241,6 @@ static void unpack_one(unsigned nr, unsigned total) } } -/* - * We unpack from the end, older files first. Now, usually - * there are deltas etc, so we'll not actually write the - * objects in that order, but we might as well try.. - */ static void unpack_all(void) { int i; diff --git a/upload-pack.c b/upload-pack.c index f6f5a7e3db..07ecdb4281 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -182,6 +182,8 @@ static void create_pack_file(void) ssize_t sz; int pe, pu, pollsize; + reset_timeout(); + pollsize = 0; pe = pu = -1; |