diff options
-rw-r--r-- | Documentation/git-archive.txt | 5 | ||||
-rw-r--r-- | Documentation/git-config.txt | 2 | ||||
-rw-r--r-- | Documentation/git-filter-branch.txt | 5 | ||||
-rw-r--r-- | builtin-add.c | 3 | ||||
-rw-r--r-- | builtin-grep.c | 90 | ||||
-rw-r--r-- | builtin-log.c | 31 | ||||
-rw-r--r-- | contrib/emacs/git.el | 197 | ||||
-rw-r--r-- | diff-lib.c | 2 | ||||
-rw-r--r-- | diff.c | 2 | ||||
-rw-r--r-- | diffcore-rename.c | 19 | ||||
-rwxr-xr-x | git-clone.sh | 6 | ||||
-rwxr-xr-x | t/t2200-add-update.sh | 11 | ||||
-rwxr-xr-x | t/t7002-grep.sh | 4 | ||||
-rw-r--r-- | templates/hooks--update | 2 | ||||
-rw-r--r-- | wt-status.c | 1 |
15 files changed, 296 insertions, 84 deletions
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt index f2080eb6ad..e1e2d60fef 100644 --- a/Documentation/git-archive.txt +++ b/Documentation/git-archive.txt @@ -15,7 +15,8 @@ SYNOPSIS DESCRIPTION ----------- Creates an archive of the specified format containing the tree -structure for the named tree. If <prefix> is specified it is +structure for the named tree, and writes it out to the standard +output. If <prefix> is specified it is prepended to the filenames in the archive. 'git-archive' behaves differently when given a tree ID versus when @@ -31,7 +32,7 @@ OPTIONS ------- --format=<fmt>:: - Format of the resulting archive: 'tar', 'zip'... The default + Format of the resulting archive: 'tar' or 'zip'. The default is 'tar'. --list, -l:: diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 5b794f4399..a592b61e2f 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -142,7 +142,7 @@ FILES If not set explicitly with '--file', there are three files where git-config will search for configuration options: -.git/config:: +$GIT_DIR/config:: Repository specific configuration file. (The filename is of course relative to the repository root, not the working directory.) diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index 29bb8cec0c..c878ed395e 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -220,11 +220,6 @@ git filter-branch --commit-filter ' fi' HEAD ------------------------------------------------------------------------------ -Note that the changes introduced by the commits, and not reverted by -subsequent commits, will still be in the rewritten branch. If you want -to throw out _changes_ together with the commits, you should use the -interactive mode of gitlink:git-rebase[1]. - The function 'skip_commits' is defined as follows: -------------------------- diff --git a/builtin-add.c b/builtin-add.c index 105a9f0e1f..3d8b8b4f89 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -95,9 +95,10 @@ static void update_callback(struct diff_queue_struct *q, const char *path = p->one->path; switch (p->status) { default: - die("unexpacted diff status %c", p->status); + die("unexpected diff status %c", p->status); case DIFF_STATUS_UNMERGED: case DIFF_STATUS_MODIFIED: + case DIFF_STATUS_TYPE_CHANGED: add_file_to_cache(path, verbose); break; case DIFF_STATUS_DELETED: diff --git a/builtin-grep.c b/builtin-grep.c index e13cb31f2b..c7b45c4d58 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -187,6 +187,78 @@ static int exec_grep(int argc, const char **argv) else die("maximum number of args exceeded"); \ } while (0) +/* + * If you send a singleton filename to grep, it does not give + * the name of the file. GNU grep has "-H" but we would want + * that behaviour in a portable way. + * + * So we keep two pathnames in argv buffer unsent to grep in + * the main loop if we need to do more than one grep. + */ +static int flush_grep(struct grep_opt *opt, + int argc, int arg0, const char **argv, int *kept) +{ + int status; + int count = argc - arg0; + const char *kept_0 = NULL; + + if (count <= 2) { + /* + * Because we keep at least 2 paths in the call from + * the main loop (i.e. kept != NULL), and MAXARGS is + * far greater than 2, this usually is a call to + * conclude the grep. However, the user could attempt + * to overflow the argv buffer by giving too many + * options to leave very small number of real + * arguments even for the call in the main loop. + */ + if (kept) + die("insanely many options to grep"); + + /* + * If we have two or more paths, we do not have to do + * anything special, but we need to push /dev/null to + * get "-H" behaviour of GNU grep portably but when we + * are not doing "-l" nor "-L" nor "-c". + */ + if (count == 1 && + !opt->name_only && + !opt->unmatch_name_only && + !opt->count) { + argv[argc++] = "/dev/null"; + argv[argc] = NULL; + } + } + + else if (kept) { + /* + * Called because we found many paths and haven't finished + * iterating over the cache yet. We keep two paths + * for the concluding call. argv[argc-2] and argv[argc-1] + * has the last two paths, so save the first one away, + * replace it with NULL while sending the list to grep, + * and recover them after we are done. + */ + *kept = 2; + kept_0 = argv[argc-2]; + argv[argc-2] = NULL; + argc -= 2; + } + + status = exec_grep(argc, argv); + + if (kept_0) { + /* + * Then recover them. Now the last arg is beyond the + * terminating NULL which is at argc, and the second + * from the last is what we saved away in kept_0 + */ + argv[arg0++] = kept_0; + argv[arg0] = argv[argc+1]; + } + return status; +} + static int external_grep(struct grep_opt *opt, const char **paths, int cached) { int i, nr, argc, hit, len, status; @@ -253,22 +325,12 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) push_arg(p->pattern); } - /* - * To make sure we get the header printed out when we want it, - * add /dev/null to the paths to grep. This is unnecessary - * (and wrong) with "-l" or "-L", which always print out the - * name anyway. - * - * GNU grep has "-H", but this is portable. - */ - if (!opt->name_only && !opt->unmatch_name_only) - push_arg("/dev/null"); - hit = 0; argc = nr; for (i = 0; i < active_nr; i++) { struct cache_entry *ce = active_cache[i]; char *name; + int kept; if (!S_ISREG(ntohl(ce->ce_mode))) continue; if (!pathspec_matches(paths, ce->name)) @@ -283,10 +345,10 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) argv[argc++] = name; if (argc < MAXARGS && !ce_stage(ce)) continue; - status = exec_grep(argc, argv); + status = flush_grep(opt, argc, nr, argv, &kept); if (0 < status) hit = 1; - argc = nr; + argc = nr + kept; if (ce_stage(ce)) { do { i++; @@ -296,7 +358,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) } } if (argc > nr) { - status = exec_grep(argc, argv); + status = flush_grep(opt, argc, nr, argv, NULL); if (0 < status) hit = 1; } diff --git a/builtin-log.c b/builtin-log.c index fa81c25920..c6cc3aef52 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -437,6 +437,34 @@ static void gen_message_id(char *dest, unsigned int length, char *base) (int)(email_end - email_start - 1), email_start + 1); } +static const char *clean_message_id(const char *msg_id) +{ + char ch; + const char *a, *z, *m; + char *n; + size_t len; + + m = msg_id; + while ((ch = *m) && (isspace(ch) || (ch == '<'))) + m++; + a = m; + z = NULL; + while ((ch = *m)) { + if (!isspace(ch) && (ch != '>')) + z = m; + m++; + } + if (!z) + die("insane in-reply-to: %s", msg_id); + if (++z == m) + return a; + len = z - a; + n = xmalloc(len + 1); + memcpy(n, a, len); + n[len] = 0; + return n; +} + int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; @@ -625,7 +653,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (numbered) rev.total = total + start_number - 1; rev.add_signoff = add_signoff; - rev.ref_message_id = in_reply_to; + if (in_reply_to) + rev.ref_message_id = clean_message_id(in_reply_to); while (0 <= --nr) { int shown; commit = list[nr]; diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 280557ecd4..2d77fd47ec 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -97,6 +97,21 @@ if there is already one that displays the same directory." :group 'git :type 'string) +(defcustom git-show-uptodate nil + "Whether to display up-to-date files." + :group 'git + :type 'boolean) + +(defcustom git-show-ignored nil + "Whether to display ignored files." + :group 'git + :type 'boolean) + +(defcustom git-show-unknown t + "Whether to display unknown files." + :group 'git + :type 'boolean) + (defface git-status-face '((((class color) (background light)) (:foreground "purple")) @@ -479,6 +494,27 @@ and returns the process output as a string." (setf (git-fileinfo->orig-name info) nil) (setf (git-fileinfo->needs-refresh info) t)))) +(defun git-set-filenames-state (status files state) + "Set the state of a list of named files." + (when files + (setq files (sort files #'string-lessp)) + (let ((file (pop files)) + (node (ewoc-nth status 0))) + (while (and file node) + (let ((info (ewoc-data node))) + (cond ((string-lessp (git-fileinfo->name info) file) + (setq node (ewoc-next status node))) + ((string-equal (git-fileinfo->name info) file) + (unless (eq (git-fileinfo->state info) state) + (setf (git-fileinfo->state info) state) + (setf (git-fileinfo->rename-state info) nil) + (setf (git-fileinfo->orig-name info) nil) + (setf (git-fileinfo->needs-refresh info) t)) + (setq file (pop files))) + (t (setq file (pop files))))))) + (unless state ;; delete files whose state has been set to nil + (ewoc-filter status (lambda (info) (git-fileinfo->state info)))))) + (defun git-state-code (code) "Convert from a string to a added/deleted/modified state." (case (string-to-char code) @@ -532,19 +568,36 @@ and returns the process output as a string." " " (git-escape-file-name (git-fileinfo->name info)) (git-rename-as-string info)))) -(defun git-insert-fileinfo (status info &optional refresh) - "Insert INFO in the status buffer, optionally refreshing an existing one." - (let ((node (and refresh - (git-find-status-file status (git-fileinfo->name info))))) - (setf (git-fileinfo->needs-refresh info) t) - (when node ;preserve the marked flag - (setf (git-fileinfo->marked info) (git-fileinfo->marked (ewoc-data node)))) - (if node (setf (ewoc-data node) info) (ewoc-enter-last status info)))) +(defun git-insert-info-list (status infolist) + "Insert a list of file infos in the status buffer, replacing existing ones if any." + (setq infolist (sort infolist + (lambda (info1 info2) + (string-lessp (git-fileinfo->name info1) + (git-fileinfo->name info2))))) + (let ((info (pop infolist)) + (node (ewoc-nth status 0))) + (while info + (setf (git-fileinfo->needs-refresh info) t) + (cond ((not node) + (ewoc-enter-last status info) + (setq info (pop infolist))) + ((string-lessp (git-fileinfo->name (ewoc-data node)) + (git-fileinfo->name info)) + (setq node (ewoc-next status node))) + ((string-equal (git-fileinfo->name (ewoc-data node)) + (git-fileinfo->name info)) + ;; preserve the marked flag + (setf (git-fileinfo->marked info) (git-fileinfo->marked (ewoc-data node))) + (setf (ewoc-data node) info) + (setq info (pop infolist))) + (t + (ewoc-enter-before status node info) + (setq info (pop infolist))))))) (defun git-run-diff-index (status files) "Run git-diff-index on FILES and parse the results into STATUS. Return the list of files that haven't been handled." - (let ((refresh files)) + (let (infolist) (with-temp-buffer (apply #'git-run-command t nil "diff-index" "-z" "-M" "HEAD" "--" files) (goto-char (point-min)) @@ -558,13 +611,14 @@ Return the list of files that haven't been handled." (new-name (match-string 8))) (if new-name ; copy or rename (if (eq ?C (string-to-char state)) - (git-insert-fileinfo status (git-create-fileinfo 'added new-name old-perm new-perm 'copy name) refresh) - (git-insert-fileinfo status (git-create-fileinfo 'deleted name 0 0 'rename new-name) refresh) - (git-insert-fileinfo status (git-create-fileinfo 'added new-name old-perm new-perm 'rename name)) refresh) - (git-insert-fileinfo status (git-create-fileinfo (git-state-code state) name old-perm new-perm) refresh)) + (push (git-create-fileinfo 'added new-name old-perm new-perm 'copy name) infolist) + (push (git-create-fileinfo 'deleted name 0 0 'rename new-name) infolist) + (push (git-create-fileinfo 'added new-name old-perm new-perm 'rename name) infolist)) + (push (git-create-fileinfo (git-state-code state) name old-perm new-perm) infolist)) (setq files (delete name files)) - (when new-name (setq files (delete new-name files))))))) - files) + (when new-name (setq files (delete new-name files)))))) + (git-insert-info-list status infolist) + files)) (defun git-find-status-file (status file) "Find a given file in the status ewoc and return its node." @@ -576,16 +630,16 @@ Return the list of files that haven't been handled." (defun git-run-ls-files (status files default-state &rest options) "Run git-ls-files on FILES and parse the results into STATUS. Return the list of files that haven't been handled." - (let ((refresh files)) + (let (infolist) (with-temp-buffer - (apply #'git-run-command t nil "ls-files" "-z" "-t" (append options (list "--") files)) + (apply #'git-run-command t nil "ls-files" "-z" (append options (list "--") files)) (goto-char (point-min)) - (while (re-search-forward "\\([HMRCK?]\\) \\([^\0]*\\)\0" nil t 1) - (let ((state (match-string 1)) - (name (match-string 2))) - (git-insert-fileinfo status (git-create-fileinfo (or (git-state-code state) default-state) name) refresh) - (setq files (delete name files)))))) - files) + (while (re-search-forward "\\([^\0]*\\)\0" nil t 1) + (let ((name (match-string 1))) + (push (git-create-fileinfo default-state name) infolist) + (setq files (delete name files))))) + (git-insert-info-list status infolist) + files)) (defun git-run-ls-unmerged (status files) "Run git-ls-files -u on FILES and parse the results into STATUS." @@ -594,9 +648,8 @@ Return the list of files that haven't been handled." (goto-char (point-min)) (let (unmerged-files) (while (re-search-forward "[0-7]\\{6\\} [0-9a-f]\\{40\\} [123]\t\\([^\0]+\\)\0" nil t) - (let ((node (git-find-status-file status (match-string 1)))) - (when node (push (ewoc-data node) unmerged-files)))) - (git-set-files-state unmerged-files 'unmerged)))) + (push (match-string 1) unmerged-files)) + (git-set-filenames-state status unmerged-files 'unmerged)))) (defun git-get-exclude-files () "Get the list of exclude files to pass to git-ls-files." @@ -608,34 +661,30 @@ Return the list of files that haven't been handled." (push config files)) files)) +(defun git-run-ls-files-with-excludes (status files default-state &rest options) + "Run git-ls-files on FILES with appropriate --exclude-from options." + (let ((exclude-files (git-get-exclude-files))) + (apply #'git-run-ls-files status files default-state + (concat "--exclude-per-directory=" git-per-dir-ignore-file) + (append options (mapcar (lambda (f) (concat "--exclude-from=" f)) exclude-files))))) + (defun git-update-status-files (files &optional default-state) "Update the status of FILES from the index." (unless git-status (error "Not in git-status buffer.")) - (let* ((status git-status) - (remaining-files + (unless files + (when git-show-uptodate (git-run-ls-files git-status nil 'uptodate "-c"))) + (let* ((remaining-files (if (git-empty-db-p) ; we need some special handling for an empty db - (git-run-ls-files status files 'added "-c") - (git-run-diff-index status files)))) - (git-run-ls-unmerged status files) - (when (or (not files) remaining-files) - (let ((exclude-files (git-get-exclude-files))) - (setq remaining-files (apply #'git-run-ls-files status remaining-files 'unknown "-o" - (concat "--exclude-per-directory=" git-per-dir-ignore-file) - (mapcar (lambda (f) (concat "--exclude-from=" f)) exclude-files))))) - ; mark remaining files with the default state (or remove them if nil) - (when remaining-files - (if default-state - (ewoc-map (lambda (info) - (when (member (git-fileinfo->name info) remaining-files) - (git-set-files-state (list info) default-state)) - nil) - status) - (ewoc-filter status - (lambda (info files) - (not (member (git-fileinfo->name info) files))) - remaining-files))) + (git-run-ls-files git-status files 'added "-c") + (git-run-diff-index git-status files)))) + (git-run-ls-unmerged git-status files) + (when (or remaining-files (and git-show-unknown (not files))) + (setq remaining-files (git-run-ls-files-with-excludes git-status remaining-files 'unknown "-o"))) + (when (or remaining-files (and git-show-ignored (not files))) + (setq remaining-files (git-run-ls-files-with-excludes git-status remaining-files 'ignored "-o" "-i"))) + (git-set-filenames-state git-status remaining-files default-state) (git-refresh-files) - (git-refresh-ewoc-hf status))) + (git-refresh-ewoc-hf git-status))) (defun git-marked-files () "Return a list of all marked files, or if none a list containing just the file at cursor position." @@ -853,7 +902,7 @@ Return the list of files that haven't been handled." (defun git-add-file () "Add marked file(s) to the index cache." (interactive) - (let ((files (git-get-filenames (git-marked-files-state 'unknown)))) + (let ((files (git-get-filenames (git-marked-files-state 'unknown 'ignored)))) (unless files (push (file-relative-name (read-file-name "File to add: " nil nil t)) files)) (apply #'git-run-command nil nil "update-index" "--add" "--" files) @@ -871,7 +920,7 @@ Return the list of files that haven't been handled." (defun git-remove-file () "Remove the marked file(s)." (interactive) - (let ((files (git-get-filenames (git-marked-files-state 'added 'modified 'unknown 'uptodate)))) + (let ((files (git-get-filenames (git-marked-files-state 'added 'modified 'unknown 'uptodate 'ignored)))) (unless files (push (file-relative-name (read-file-name "File to remove: " nil nil t)) files)) (if (yes-or-no-p @@ -916,11 +965,41 @@ Return the list of files that haven't been handled." (interactive) (ewoc-filter git-status (lambda (info) - (not (or (eq (git-fileinfo->state info) 'ignored) - (eq (git-fileinfo->state info) 'uptodate))))) + (case (git-fileinfo->state info) + ('ignored git-show-ignored) + ('uptodate git-show-uptodate) + ('unknown git-show-unknown) + (t t)))) (unless (ewoc-nth git-status 0) ; refresh header if list is empty (git-refresh-ewoc-hf git-status))) +(defun git-toggle-show-uptodate () + "Toogle the option for showing up-to-date files." + (interactive) + (if (setq git-show-uptodate (not git-show-uptodate)) + (git-refresh-status) + (git-remove-handled))) + +(defun git-toggle-show-ignored () + "Toogle the option for showing ignored files." + (interactive) + (if (setq git-show-ignored (not git-show-ignored)) + (progn + (git-run-ls-files-with-excludes git-status nil 'ignored "-o" "-i") + (git-refresh-files) + (git-refresh-ewoc-hf git-status)) + (git-remove-handled))) + +(defun git-toggle-show-unknown () + "Toogle the option for showing unknown files." + (interactive) + (if (setq git-show-unknown (not git-show-unknown)) + (progn + (git-run-ls-files-with-excludes git-status nil 'unknown "-o") + (git-refresh-files) + (git-refresh-ewoc-hf git-status)) + (git-remove-handled))) + (defun git-setup-diff-buffer (buffer) "Setup a buffer for displaying a diff." (let ((dir default-directory)) @@ -1146,7 +1225,8 @@ Return the list of files that haven't been handled." (unless git-status-mode-map (let ((map (make-keymap)) - (diff-map (make-sparse-keymap))) + (diff-map (make-sparse-keymap)) + (toggle-map (make-sparse-keymap))) (suppress-keymap map) (define-key map "?" 'git-help) (define-key map "h" 'git-help) @@ -1170,6 +1250,7 @@ Return the list of files that haven't been handled." (define-key map "q" 'git-status-quit) (define-key map "r" 'git-remove-file) (define-key map "R" 'git-resolve-file) + (define-key map "t" toggle-map) (define-key map "T" 'git-toggle-all-marks) (define-key map "u" 'git-unmark-file) (define-key map "U" 'git-revert-file) @@ -1186,6 +1267,11 @@ Return the list of files that haven't been handled." (define-key diff-map "h" 'git-diff-file-merge-head) (define-key diff-map "m" 'git-diff-file-mine) (define-key diff-map "o" 'git-diff-file-other) + ; the toggle submap + (define-key toggle-map "u" 'git-toggle-show-uptodate) + (define-key toggle-map "i" 'git-toggle-show-ignored) + (define-key toggle-map "k" 'git-toggle-show-unknown) + (define-key toggle-map "m" 'git-toggle-all-marks) (setq git-status-mode-map map))) ;; git mode should only run in the *git status* buffer @@ -1207,6 +1293,9 @@ Commands: (let ((status (ewoc-create 'git-fileinfo-prettyprint "" ""))) (set (make-local-variable 'git-status) status)) (set (make-local-variable 'list-buffers-directory) default-directory) + (make-local-variable 'git-show-uptodate) + (make-local-variable 'git-show-ignored) + (make-local-variable 'git-show-unknown) (run-hooks 'git-status-mode-hook))) (defun git-find-status-buffer (dir) diff --git a/diff-lib.c b/diff-lib.c index f5568c3b36..da5571302d 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -298,6 +298,8 @@ int setup_diff_no_index(struct rev_info *revs, revs->diffopt.nr_paths = 2; revs->diffopt.no_index = 1; revs->max_count = -2; + if (diff_setup_done(&revs->diffopt) < 0) + die("diff_setup_done failed"); return 0; } @@ -17,7 +17,7 @@ #endif static int diff_detect_rename_default; -static int diff_rename_limit_default = -1; +static int diff_rename_limit_default = 100; static int diff_use_color_default; int diff_auto_refresh_index = 1; diff --git a/diffcore-rename.c b/diffcore-rename.c index 6bde4396f2..41b35c3a9e 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -298,10 +298,25 @@ void diffcore_rename(struct diff_options *options) else if (detect_rename == DIFF_DETECT_COPY) register_rename_src(p->one, 1, p->score); } - if (rename_dst_nr == 0 || rename_src_nr == 0 || - (0 < rename_limit && rename_limit < rename_dst_nr)) + if (rename_dst_nr == 0 || rename_src_nr == 0) goto cleanup; /* nothing to do */ + /* + * This basically does a test for the rename matrix not + * growing larger than a "rename_limit" square matrix, ie: + * + * rename_dst_nr * rename_src_nr > rename_limit * rename_limit + * + * but handles the potential overflow case specially (and we + * assume at least 32-bit integers) + */ + if (rename_limit <= 0 || rename_limit > 32767) + rename_limit = 32767; + if (rename_dst_nr > rename_limit && rename_src_nr > rename_limit) + goto cleanup; + if (rename_dst_nr * rename_src_nr > rename_limit * rename_limit) + goto cleanup; + /* We really want to cull the candidates list early * with cheap tests in order to avoid doing deltas. * The first round matches up the up-to-date entries, diff --git a/git-clone.sh b/git-clone.sh index 18003ab4b3..5e582fe247 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -34,7 +34,11 @@ fi http_fetch () { # $1 = Remote, $2 = Local - curl -nsfL $curl_extra_args "$1" >"$2" + curl -nsfL $curl_extra_args "$1" >"$2" || + case $? in + 126|127) exit ;; + *) return $? ;; + esac } clone_dumb_http () { diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index 61d08bb431..eb1ced3c37 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -16,11 +16,12 @@ only the updates to dir/sub.' test_expect_success setup ' echo initial >check && echo initial >top && + echo initial >foo && mkdir dir1 dir2 && echo initial >dir1/sub1 && echo initial >dir1/sub2 && echo initial >dir2/sub3 && - git add check dir1 dir2 top && + git add check dir1 dir2 top foo && test_tick git-commit -m initial && @@ -76,4 +77,12 @@ test_expect_success 'change gets noticed' ' ' +test_expect_success 'replace a file with a symlink' ' + + rm foo && + ln -s top foo && + git add -u -- foo + +' + test_done diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh index 6bfb899ed1..68b2b92879 100755 --- a/t/t7002-grep.sh +++ b/t/t7002-grep.sh @@ -107,6 +107,10 @@ do diff expected actual ' + test_expect_failure "grep -c $L (no /dev/null)" ' + git grep -c test $H | grep -q "/dev/null" + ' + done test_done diff --git a/templates/hooks--update b/templates/hooks--update index 9d3795c6d0..d8c76264be 100644 --- a/templates/hooks--update +++ b/templates/hooks--update @@ -42,7 +42,7 @@ fi # --- Check types # if $newrev is 0000...0000, it's a commit to delete a branch -if [ -z "${newrev##0*}" ]; then +if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then newrev_type=commit else newrev_type=$(git-cat-file -t $newrev) diff --git a/wt-status.c b/wt-status.c index 52054201c2..10ce6eedc7 100644 --- a/wt-status.c +++ b/wt-status.c @@ -227,6 +227,7 @@ static void wt_status_print_updated(struct wt_status *s) rev.diffopt.format_callback = wt_status_print_updated_cb; rev.diffopt.format_callback_data = s; rev.diffopt.detect_rename = 1; + rev.diffopt.rename_limit = 100; wt_read_cache(s); run_diff_index(&rev, 1); } |