Merge branch 'jc/cachetree' into cr/reset

* jc/cachetree:
  Simplify cache API
  git-format-patch --in-reply-to: accept <message@id> with angle brackets
  git-add -u: do not barf on type changes
  Remove duplicate note about removing commits with git-filter-branch
  git-clone: improve error message if curl program is missing or not executable
  git.el: Allow the add and remove commands to be applied to ignored files.
  git.el: Allow selecting whether to display uptodate/unknown/ignored files.
  git.el: Keep the status buffer sorted by filename.
  hooks--update: Explicitly check for all zeros for a deleted ref.
This commit is contained in:
Junio C Hamano 2007-09-14 01:19:30 -07:00
commit 58f6fb53dd
11 changed files with 184 additions and 81 deletions

View File

@ -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:
--------------------------

View File

@ -98,11 +98,11 @@ static void update_callback(struct diff_queue_struct *q,
die("unexpacted 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:
remove_file_from_cache(path);
cache_tree_invalidate_path(active_cache_tree, path);
if (verbose)
printf("remove '%s'\n", path);
break;

View File

@ -2394,7 +2394,6 @@ static void remove_file(struct patch *patch, int rmdir_empty)
if (update_index) {
if (remove_file_from_cache(patch->old_name) < 0)
die("unable to remove %s from index", patch->old_name);
cache_tree_invalidate_path(active_cache_tree, patch->old_name);
}
if (!cached) {
if (S_ISGITLINK(patch->old_mode)) {
@ -2549,7 +2548,6 @@ static void create_file(struct patch *patch)
mode = S_IFREG | 0644;
create_one_file(path, mode, buf, size);
add_index_file(path, mode, buf, size);
cache_tree_invalidate_path(active_cache_tree, path);
}
/* phase zero is to remove, phase one is to create */

View File

@ -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];

View File

@ -276,11 +276,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
add_file_to_cache(path, verbose);
}
for (i = 0; i < deleted.nr; i++) {
const char *path = deleted.items[i].path;
remove_file_from_cache(path);
cache_tree_invalidate_path(active_cache_tree, path);
}
for (i = 0; i < deleted.nr; i++)
remove_file_from_cache(deleted.items[i].path);
if (active_cache_changed) {
if (write_cache(newfd, active_cache, active_nr) ||

View File

@ -227,7 +227,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
if (remove_file_from_cache(path))
die("git-rm: unable to remove %s", path);
cache_tree_invalidate_path(active_cache_tree, path);
}
if (show_only)

View File

@ -195,11 +195,6 @@ static int process_path(const char *path)
int len;
struct stat st;
/* We probably want to do this in remove_file_from_cache() and
* add_cache_entry() instead...
*/
cache_tree_invalidate_path(active_cache_tree, path);
/*
* First things first: get the stat information, to decide
* what to do about the pathname!
@ -239,7 +234,6 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
return error("%s: cannot add to the index - missing --add option?",
path);
report("add '%s'", path);
cache_tree_invalidate_path(active_cache_tree, path);
return 0;
}
@ -284,7 +278,6 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
die("Unable to mark file %s", path);
goto free_return;
}
cache_tree_invalidate_path(active_cache_tree, path);
if (force_remove) {
if (remove_file_from_cache(p))
@ -367,7 +360,6 @@ static void read_index_info(int line_termination)
free(path_name);
continue;
}
cache_tree_invalidate_path(active_cache_tree, path_name);
if (!mode) {
/* mode == 0 means there is no such path -- remove */
@ -474,7 +466,6 @@ static int unresolve_one(const char *path)
goto free_return;
}
cache_tree_invalidate_path(active_cache_tree, path);
remove_file_from_cache(path);
if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) {
error("%s: cannot add our version to the index.", path);

View File

@ -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)

View File

@ -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 () {

View File

@ -346,6 +346,7 @@ int remove_file_from_index(struct index_state *istate, const char *path)
int pos = index_name_pos(istate, path, strlen(path));
if (pos < 0)
pos = -pos-1;
cache_tree_invalidate_path(istate->cache_tree, path);
while (pos < istate->cache_nr && !strcmp(istate->cache[pos]->name, path))
remove_index_entry_at(istate, pos);
return 0;
@ -430,7 +431,6 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)
die("unable to add %s to index",path);
if (verbose)
printf("add '%s'\n", path);
cache_tree_invalidate_path(istate->cache_tree, path);
return 0;
}
@ -698,6 +698,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
cache_tree_invalidate_path(istate->cache_tree, ce->name);
pos = index_name_pos(istate, ce->name, ntohs(ce->ce_flags));
/* existing match? Just replace it. */

View File

@ -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)