+ (stgit-assert-mode)
+ (if (< count 0)
+ (stgit-commit (- count))
+ (stgit-capture-output nil (stgit-run "uncommit" "-n" count))
+ (stgit-reload)))
+
+(defun stgit-neighbour-file ()
+ "Return the file name of the next file after point, or the
+previous file if point is at the last file within a patch."
+ (let ((old-point (point))
+ neighbour-file)
+ (and (zerop (forward-line 1))
+ (let ((f (stgit-patched-file-at-point)))
+ (and f (setq neighbour-file (stgit-file-file f)))))
+ (goto-char old-point)
+ (unless neighbour-file
+ (and (zerop (forward-line -1))
+ (let ((f (stgit-patched-file-at-point)))
+ (and f (setq neighbour-file (stgit-file-file f)))))
+ (goto-char old-point))
+ neighbour-file))
+
+(defun stgit-revert-file ()
+ "Revert the file at point, which must be in the index or the
+working tree."
+ (interactive)
+ (stgit-assert-mode)
+ (let* ((patched-file (or (stgit-patched-file-at-point)
+ (error "No file on the current line")))
+ (patch-name (stgit-patch-name-at-point))
+ (file-status (stgit-file-status patched-file))
+ (rm-file (cond ((stgit-file-copy-or-rename patched-file)
+ (stgit-file-cr-to patched-file))
+ ((eq file-status 'add)
+ (stgit-file-file patched-file))))
+ (co-file (cond ((eq file-status 'rename)
+ (stgit-file-cr-from patched-file))
+ ((not (memq file-status '(copy add)))
+ (stgit-file-file patched-file))))
+ (next-file (stgit-neighbour-file)))
+
+ (unless (memq patch-name '(:work :index))
+ (error "No index or working tree file on this line"))
+
+ (when (eq file-status 'ignore)
+ (error "Cannot revert ignored files"))
+
+ (when (eq file-status 'unknown)
+ (error "Cannot revert unknown files"))
+
+ (let ((nfiles (+ (if rm-file 1 0) (if co-file 1 0))))
+ (when (yes-or-no-p (format "Revert %d file%s? "
+ nfiles
+ (if (= nfiles 1) "" "s")))
+ (stgit-capture-output nil
+ (when rm-file
+ (stgit-run-git "rm" "-f" "-q" "--" rm-file))
+ (when co-file
+ (stgit-run-git "checkout" "HEAD" co-file)))
+ (stgit-reload)
+ (stgit-goto-patch patch-name next-file)))))
+
+(defun stgit-revert ()
+ "Revert the change at point, which must be the index, the work
+tree, or a single change in either."
+ (interactive)
+ (stgit-assert-mode)
+ (let ((patched-file (stgit-patched-file-at-point)))
+ (if patched-file
+ (stgit-revert-file)
+ (let* ((patch-name (or (stgit-patch-name-at-point)
+ (error "No patch or file at point")))
+ (patch-desc (case patch-name
+ (:index "index")
+ (:work "work tree")
+ (t (error (substitute-command-keys
+ "Use \\[stgit-delete] to delete a patch"))))))
+ (when (if (eq patch-name :work)
+ (stgit-work-tree-empty-p)
+ (stgit-index-empty-p))
+ (error (format "There are no changes in the %s to revert"
+ patch-desc)))
+ (and (eq patch-name :index)
+ (not (stgit-work-tree-empty-p))
+ (error "Cannot revert index as work tree contains unstaged changes"))
+
+ (when (yes-or-no-p (format "Revert all changes in the %s? "
+ patch-desc))
+ (if (eq patch-name :index)
+ (stgit-run-git-silent "reset" "--hard" "-q")
+ (stgit-run-git-silent "checkout" "--" "."))
+ (stgit-refresh-index)
+ (stgit-refresh-worktree)
+ (stgit-goto-patch patch-name))))))
+
+(defun stgit-resolve-file ()
+ "Resolve conflict in the file at point."
+ (interactive)
+ (stgit-assert-mode)
+ (let* ((patched-file (stgit-patched-file-at-point))
+ (patch (stgit-patch-at-point))
+ (patch-name (and patch (stgit-patch-name patch)))
+ (status (and patched-file (stgit-file-status patched-file))))
+
+ (unless (memq patch-name '(:work :index))
+ (error "No index or working tree file on this line"))
+
+ (unless (eq status 'unmerged)
+ (error "No conflict to resolve at the current line"))
+
+ (stgit-capture-output nil
+ (stgit-move-change-to-index (stgit-file-file patched-file)))
+
+ (stgit-reload)))