* [PATCH] archimport: remove files from the index before adding/updating
From: Eric Wong @ 2006-02-18 11:49 UTC (permalink / raw)
To: git, junkio
In-Reply-To: <11402390872301-git-send-email-normalperson@yhbt.net>
This fixes a bug when importing where a directory gets removed/renamed
but is immediately replaced by a file of the same name in the same
changeset.
This fix only applies to the accurate (default) strategy the moment.
This patch should also fix the fast strategy if/when it is updated
to handle the cases that would've triggered this bug.
This bug was originally found in git-svn, but I remembered I did the
same thing with archimport as well.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
git-archimport.perl | 28 +++++++++++++---------------
1 files changed, 13 insertions(+), 15 deletions(-)
011fe464212c52d46ad5b797eb1d8f86c1d77916
diff --git a/git-archimport.perl b/git-archimport.perl
index 841738d..6792624 100755
--- a/git-archimport.perl
+++ b/git-archimport.perl
@@ -346,12 +346,10 @@ sub process_patchset_accurate {
}
# update the index with all the changes we got
+ system('git-diff-files --name-only -z | '.
+ 'git-update-index --remove -z --stdin') == 0 or die "$! $?\n";
system('git-ls-files --others -z | '.
'git-update-index --add -z --stdin') == 0 or die "$! $?\n";
- system('git-ls-files --deleted -z | '.
- 'git-update-index --remove -z --stdin') == 0 or die "$! $?\n";
- system('git-ls-files -z | '.
- 'git-update-index -z --stdin') == 0 or die "$! $?\n";
return 1;
}
@@ -416,22 +414,14 @@ sub process_patchset_fast {
# imports don't give us good info
# on added files. Shame on them
if ($ps->{type} eq 'i' || $ps->{type} eq 't') {
- system('git-ls-files --others -z | '.
- 'git-update-index --add -z --stdin') == 0 or die "$! $?\n";
system('git-ls-files --deleted -z | '.
'git-update-index --remove -z --stdin') == 0 or die "$! $?\n";
+ system('git-ls-files --others -z | '.
+ 'git-update-index --add -z --stdin') == 0 or die "$! $?\n";
}
# TODO: handle removed_directories and renamed_directories:
-
- if (my $add = $ps->{new_files}) {
- while (@$add) {
- my @slice = splice(@$add, 0, 100);
- system('git-update-index','--add','--',@slice) == 0 or
- die "Error in git-update-index --add: $! $?\n";
- }
- }
-
+
if (my $del = $ps->{removed_files}) {
unlink @$del;
while (@$del) {
@@ -462,6 +452,14 @@ sub process_patchset_fast {
}
}
+ if (my $add = $ps->{new_files}) {
+ while (@$add) {
+ my @slice = splice(@$add, 0, 100);
+ system('git-update-index','--add','--',@slice) == 0 or
+ die "Error in git-update-index --add: $! $?\n";
+ }
+ }
+
if (my $mod = $ps->{modified_files}) {
while (@$mod) {
my @slice = splice(@$mod, 0, 100);
--
1.2.1.gffaf
^ permalink raw reply related
* [PATCH 5/5] Optionally work without python
From: Johannes Schindelin @ 2006-02-18 12:01 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvevdtb2j.fsf@assigned-by-dhcp.cox.net>
In some setups (notably server setups) you do not need that dependency.
Gracefully handle the absence of python when NO_PYTHON is defined.
Signed-off-by: Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
---
On Fri, 17 Feb 2006, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > +ifdef NO_PYTHON
> > + TEST_DEFS += NO_PYTHON=YesPlease
> > +endif
>
> I wonder if there is a better way to do this. All future
> NO_BLAH that may affect tests need to have something like this
> otherwise.
There is: Just an "export". This defines all variables in a
sub-make. However, if you do that, the environment gets quite
large, and some programs crash, notably xargs on the box I tested.
So, for now, use "export NO_PYTHON".
> > -default_strategies='recursive'
> > +if test -z "@@NO_PYTHON@@"; then
> > + default_strategies='recursive'
> > +else
> > + default_strategies='resolve'
> > +fi
>
> Somebody commented on this part to make it shorter...
Fixed.
> I'll take 2, 3, and 4 from this series for now. They will
> appear in "next". Thanks.
Thank you!
Makefile | 9 +++++++++
git-merge.sh | 4 ++++
t/Makefile | 6 ++++
t/t0000-basic.sh | 2 +-
t/t6021-merge-criss-cross.sh | 6 ++++++
t/t6022-merge-rename.sh | 6 ++++++
t/test-lib.sh | 2 ++
7 files changed, 32 insertions(+), 1 deletions(-)
b7c435d3d594c9826e4297ee8b0353d27ef8c5b0
diff --git a/Makefile b/Makefile
index d59eede..685b714 100644
--- a/Makefile
+++ b/Makefile
@@ -58,6 +58,8 @@ all:
# Define NO_ACCURATE_DIFF if your diff program at least sometimes misses
# a missing newline at the end of the file.
#
+# Define NO_PYTHON if you want to loose all benefits of the recursive merge.
+#
# Define COLLISION_CHECK below if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
# sufficient guarantee that no collisions between objects will ever happen.
@@ -460,6 +462,7 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_QUOTED)|' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
+ -e 's/@@NO_PYTHON@@/$(NO_PYTHON)/g' \
$@.sh >$@
chmod +x $@
@@ -548,6 +551,12 @@ doc:
### Testing rules
+
+# GNU make supports exporting all variables by "export" without parameters.
+# However, the environment gets quite big, and some programs have problems
+# with that.
+
+export NO_PYTHON
test: all
$(MAKE) -C t/ all
diff --git a/git-merge.sh b/git-merge.sh
index 74f0761..a05eeb2 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -13,6 +13,10 @@ LF='
all_strategies='recursive octopus resolve stupid ours'
default_strategies='recursive'
use_strategies=
+if test "@@NO_PYTHON@@"; then
+ all_strategies='resolve octopus stupid ours'
+ default_strategies='resolve'
+fi
dropsave() {
rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" \
diff --git a/t/Makefile b/t/Makefile
index e7e4229..4e89d23 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -12,10 +12,14 @@ SHELL_PATH_QUOTED = $(subst ','\'',$(SHE
T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
+ifdef NO_PYTHON
+ GIT_TEST_OPTS += --no-python
+endif
+
all: $(T) clean
$(T):
@echo "*** $@ ***"; '$(SHELL_PATH_QUOTED)' $@ $(GIT_TEST_OPTS)
clean:
rm -fr trash
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index c339a36..6729a18 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -42,7 +42,7 @@ fi
. ./test-lib.sh
-"$PYTHON" -c 'import subprocess' || {
+test "$no_python" || "$PYTHON" -c 'import subprocess' || {
echo >&2 'Your python seem to lack "subprocess" module.
Please check INSTALL document.'
exit 1
diff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh
index e8606c7..2623813 100755
--- a/t/t6021-merge-criss-cross.sh
+++ b/t/t6021-merge-criss-cross.sh
@@ -10,6 +10,12 @@
test_description='Test criss-cross merge'
. ./test-lib.sh
+if test "$no_python"; then
+ echo "Skipping: no python => no recursive merge"
+ test_done
+ exit 0
+fi
+
test_expect_success 'prepare repository' \
'echo "1
2
diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh
index 1292caf..a2d24b5 100755
--- a/t/t6022-merge-rename.sh
+++ b/t/t6022-merge-rename.sh
@@ -3,6 +3,12 @@
test_description='Merge-recursive merging renames'
. ./test-lib.sh
+if test "$no_python"; then
+ echo "Skipping: no python => no recursive merge"
+ test_done
+ exit 0
+fi
+
test_expect_success setup \
'
cat >A <<\EOF &&
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 7a58a86..43c8e55 100755
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -63,6 +63,8 @@ do
exit 0 ;;
-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
verbose=t; shift ;;
+ --no-python)
+ no_python=t; shift ;;
*)
break ;;
esac
--
1.2.1.g05ee-dirty
^ permalink raw reply related
* Re: [PATCH] archimport: remove files from the index before adding/updating
From: Eric Wong @ 2006-02-18 12:36 UTC (permalink / raw)
To: git, junkio, Martin Langhoff
In-Reply-To: <20060218114628.GA24678@BL4ST>
Oops, forgot to Cc Martin on this :>
--
Eric Wong
^ permalink raw reply
* Re: Why can't git-rebase back up?
From: linux @ 2006-02-18 13:00 UTC (permalink / raw)
To: junkio, linux; +Cc: git
In-Reply-To: <7vpsllowo2.fsf@assigned-by-dhcp.cox.net>
> BTW, why are we suddenly having many nameless people on this
> list, I wonder...
Oh, you know, possibilities like:
- I'm sick of being googled and quizzed about every off-the-cuff
remark I've ever made.
- My real name is not pronouncable by earthlings.
- My embittered ex joe-jobs me with porn spam whenever he finds a new
e-mail address for me.
- My day job has licensed BitKeeper and I don't want hassles from
His Larryness.
- I'm am illegal immigrant and I don't want to get noticed by la Migra.
- My name is Jamal Al-Gashey and it's *so* not worth it.
And I'm never sure if it's politer to use an obvious pseudonym or a
subtle one.
--
-Michael Baldwin <bruce5@wallamaloo.edu.au>
^ permalink raw reply
* Re: git-cvs-import retries
From: Martin Mares @ 2006-02-18 13:14 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v1wy1t9cb.fsf@assigned-by-dhcp.cox.net>
Hi Junio!
> First, one technicality. You can see what's wrong with the
> above, right? Remember, the top part of your message goes into
> the commit log, so we do not want "Hello!" nor signature.
Sorry about that, the patch was intended more for discussion than
for applying.
> I read _line() three times but its return value is the lexical
> variable $res which is initialized to 0 and then either reset to
> 0 by assignment or updated with $res += somethingelse. So I do
> not see how you can get a defined but empty string in there.
You almost convinced me that my fix couldn't have changed anything :-)
But it did and I finally understand why: _line() can exit not only
by return, but also by falling over when readline() returns undef.
In this case, something weird is returned (the most recent expression
evaluated) and it's *sometimes* the empty string.
I will send a new patch.
Have a nice fortnight
--
Martin `MJ' Mares <mj@ucw.cz> http://atrey.karlin.mff.cuni.cz/~mj/
Faculty of Math and Physics, Charles University, Prague, Czech Rep., Earth
The first myth of management is that it exists.
^ permalink raw reply
* [ANNOUNCE] qgit 1.1
From: Marco Costalba @ 2006-02-18 13:14 UTC (permalink / raw)
To: git; +Cc: proski
This is qgit-1.1
With qgit you will be able to browse revisions history, view patch
content and changed
files, graphically following different development branches.
FEATURES
- View revisions, diffs, files history, files annotation, archive tree.
- Commit changes visually cherry picking modified files.
- Apply or format patch series from selected commits, drag and
drop commits between two instances of qgit.
- qgit implements a GUI for the most common StGIT commands like push/pop
and apply/format patches. You can also create new patches or refresh
current top one using the same semantics of git commit, i.e. cherry picking
single modified files.
NEW IN THIS RELEASE
A lot of work has been done by Pavel and me from 1.0, too much to list.
A notably change from the last rc3 is a much improved GUI, courtesy of Pavel,
and various stability fixes.
Update to 1.1 is suggested for all users.
Please note that you will need git 1.2 or newer.
DOWNLOAD
SourceForge tarball link is:
http://prdownloads.sourceforge.net/qgit/qgit-1.1.tar.bz2?download
Refer to http://digilander.libero.it/mcostalba/ for additional links
and detailed change log.
Installation should be as simple as ./configure + make + make install-strip
The last one (install-strip) to have a much smaller bin with debug
info stripped.
Please refer to shipped README file for more information.
In case you prefer to clone from the public git repository:
http://digilander.libero.it/mcostalba/scm/qgit.git
you may run 'autoreconf -i' before ./configure
Marco
^ permalink raw reply
* Re: Why can't git-rebase back up?
From: Johannes Schindelin @ 2006-02-18 14:53 UTC (permalink / raw)
To: linux; +Cc: junkio, git
In-Reply-To: <20060218130056.14228.qmail@science.horizon.com>
Hi,
On Sat, 18 Feb 2006, linux@horizon.com wrote:
> > BTW, why are we suddenly having many nameless people on this
> > list, I wonder...
>
> Oh, you know, possibilities like:
>
> - I'm sick of being googled and quizzed about every off-the-cuff
> remark I've ever made.
> - My real name is not pronouncable by earthlings.
> - My embittered ex joe-jobs me with porn spam whenever he finds a new
> e-mail address for me.
> - My day job has licensed BitKeeper and I don't want hassles from
> His Larryness.
> - I'm am illegal immigrant and I don't want to get noticed by la Migra.
> - My name is Jamal Al-Gashey and it's *so* not worth it.
- I'm working for NSA, and my name is classified.
- If people knew who I am, they would fault me for my starting a war,
instead of commenting on my patches.
- I could use a pseudonym, but that would be a lie, and since you cannot
tell if it is a pseudonym to begin with, it is an even bigger lie, and
if I did not use a pseudonym, you could mistake it for one, and I could
not live with that lie at all. (Recurse ad infinitum.)
Having said all that, I think it is important to provide a real and
traceable name with patches (at least patches which do not do obvious
things, like fix typos). If only for the reason that incompetent and
malign people like to sue not only each other.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] git-rev-parse: Fix --short= option parsing
From: Jonas Fonseca @ 2006-02-18 15:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v7j7tupn7.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote Fri, Feb 17, 2006:
> > Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
> >
> > ---
> > commit 013b99654ee464856d266a72f0203d0fee2b0d11
> > tree 3c961d6ebb8b9805ee3950ec081679de15f5a9ba
> > parent 16e2efc524d181cf46dcb252532139a0aff4a28f
> > author Jonas Fonseca <fonseca@diku.dk> Sat, 18 Feb 2006 02:05:11 +0100
> > committer Jonas Fonseca <fonseca@antimatter.localdomain> Sat, 18 Feb 2006 02:05:11 +0100
>
> BTW, what git-based tool do you use to spit out this ugly format?
Cogito.
> Full object name of the parent commit is useful only if the
> recipient has that object, and it is not one of mine, so it is
> unlikely nobody but you would have it. Name of the tree is what
> you would get _after_ applying this patch, so it also is not
> very useful for e-mail communication.
I agree most of this is useless and will look into making a patch to so
Cogito will also use the more or less standard From and Date headers
with parent prefixed to the diff.
--
Jonas Fonseca
^ permalink raw reply
* Re: contrib/ area
From: Alexandre Julliard @ 2006-02-18 16:49 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vu0axupnx.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
> Alexandre Julliard <julliard@winehq.org> writes:
>
>> Is there interest in an emacs interface for git? I posted a first
>> version (http://marc.theaimsgroup.com/?l=git&m=113313040724346&w=2)
>> some time ago, I'd be happy to send you a patch with my latest version
>> if you want to include it.
>
> Martin already said he wants it, and I would second that. VC
> backend is one of the things I kept in the TODO list for quite a
> while (I think since early September 2005)...
Actually the interface I wrote (patch in separate mail) is not an
emacs VC backend, it's a project tree browser similar to pcl-cvs. It's
IMO a much better fit to the git philosophy than the per-file VC
hooks. But I'm planning to add VC backend support eventually...
--
Alexandre Julliard
julliard@winehq.org
^ permalink raw reply
* [PATCH] Add an Emacs interface in contrib.
From: Alexandre Julliard @ 2006-02-18 16:50 UTC (permalink / raw)
To: git
This is an Emacs interface for git. The user interface is modeled on
pcl-cvs. It has been developed on Emacs 21 and will probably need some
tweaking to work on XEmacs.
The basic command is 'M-x git-status' which displays a buffer listing
modified files in the selected project tree. In that buffer the
following features are supported:
- add/remove files
- list unknown files
- commit marked files
- manage .gitignore
- commit merges based on MERGE_HEAD
- revert files to the HEAD version
- resolve conflicts with smerge or ediff
- diff files against HEAD/base/mine/other or combined diff
- get a log of the revisions for specified files
There are plenty of unimplemented features too, see the TODO list at
the top of the file...
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
---
contrib/emacs/git.el | 956 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 956 insertions(+), 0 deletions(-)
create mode 100644 contrib/emacs/git.el
fd1fee63b25d241f6f345fa33bdc6fd7554841dc
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
new file mode 100644
index 0000000..8f23477
--- /dev/null
+++ b/contrib/emacs/git.el
@@ -0,0 +1,956 @@
+;;; git.el --- A user interface for git
+
+;; Copyright (C) 2005, 2006 Alexandre Julliard <julliard@winehq.org>
+
+;; Version: 1.0
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2 of
+;; the License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be
+;; useful, but WITHOUT ANY WARRANTY; without even the implied
+;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+;; PURPOSE. See the GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public
+;; License along with this program; if not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+;; MA 02111-1307 USA
+
+;;; Commentary:
+
+;; This file contains an interface for the git version control
+;; system. It provides easy access to the most frequently used git
+;; commands. The user interface is as far as possible identical to
+;; that of the PCL-CVS mode.
+;;
+;; To install: put this file on the load-path and place the following
+;; in your .emacs file:
+;;
+;; (require 'git)
+;;
+;; To start: `M-x git-status'
+;;
+;; TODO
+;; - portability to XEmacs
+;; - better handling of subprocess errors
+;; - hook into file save (after-save-hook)
+;; - diff against other branch
+;; - renaming files from the status buffer
+;; - support for appending signed-off-by
+;; - creating tags
+;; - fetch/pull
+;; - switching branches
+;; - revlist browser
+;; - git-show-branch browser
+;; - customize support
+;; - menus
+;;
+
+(eval-when-compile (require 'cl))
+(require 'ewoc)
+
+
+;;;; Faces
+;;;; ------------------------------------------------------------
+
+(defface git-status-face
+ '((((class color) (background light)) (:foreground "purple")))
+ "Git mode face used to highlight added and modified files.")
+
+(defface git-unmerged-face
+ '((((class color) (background light)) (:foreground "red" :bold t)))
+ "Git mode face used to highlight unmerged files.")
+
+(defface git-unknown-face
+ '((((class color) (background light)) (:foreground "goldenrod" :bold t)))
+ "Git mode face used to highlight unknown files.")
+
+(defface git-uptodate-face
+ '((((class color) (background light)) (:foreground "grey60")))
+ "Git mode face used to highlight up-to-date files.")
+
+(defface git-ignored-face
+ '((((class color) (background light)) (:foreground "grey60")))
+ "Git mode face used to highlight ignored files.")
+
+(defface git-mark-face
+ '((((class color) (background light)) (:foreground "red" :bold t)))
+ "Git mode face used for the file marks.")
+
+(defface git-header-face
+ '((((class color) (background light)) (:foreground "blue")))
+ "Git mode face used for commit headers.")
+
+(defface git-separator-face
+ '((((class color) (background light)) (:foreground "brown")))
+ "Git mode face used for commit separator.")
+
+(defface git-permission-face
+ '((((class color) (background light)) (:foreground "green" :bold t)))
+ "Git mode face used for permission changes.")
+
+(defvar git-committer-name nil
+ "*User name to use for commits.
+If not set, fall back to `add-log-full-name' and then `user-full-name'.")
+
+(defvar git-committer-email nil
+ "*Email address to use for commits.
+If not set, fall back to `add-log-mailing-address' and then `user-mail-address'.")
+
+(defvar git-commits-coding-system 'utf-8
+ "Default coding system for git commits.")
+
+(defconst git-log-msg-separator "--- log message follows this line ---")
+
+(defconst git-per-dir-ignore-file ".gitignore"
+ "Name of the per-directory ignore file.")
+
+
+;;;; Utilities
+;;;; ------------------------------------------------------------
+
+(defun git-get-env-strings (env)
+ "Build a list of NAME=VALUE strings from a list of environment strings."
+ (mapcar (lambda (entry) (concat (car entry) "=" (cdr entry))) env))
+
+(defun git-call-process-env (buffer env &rest args)
+ "Wrapper for call-process that sets environment strings."
+ (if env
+ (apply #'call-process "env" nil buffer nil
+ (append (git-get-env-strings env) (list "git") args))
+ (apply #'call-process "git" nil buffer nil args)))
+
+(defun git-run-process-region (buffer start end program args)
+ "Run a git process with a buffer region as input."
+ (let ((output-buffer (current-buffer))
+ (dir default-directory))
+ (with-current-buffer buffer
+ (cd dir)
+ (apply #'call-process-region start end program
+ nil (list output-buffer nil) nil args))))
+
+(defun git-run-command-buffer (buffer-name &rest args)
+ "Run a git command, sending the output to a buffer named BUFFER-NAME."
+ (let ((dir default-directory)
+ (buffer (get-buffer-create buffer-name)))
+ (message "Running git %s..." (car args))
+ (with-current-buffer buffer
+ (let ((default-directory dir)
+ (buffer-read-only nil))
+ (erase-buffer)
+ (apply #'git-call-process-env buffer nil args)))
+ (message "Running git %s...done" (car args))
+ buffer))
+
+(defun git-run-command (buffer env &rest args)
+ (message "Running git %s..." (car args))
+ (apply #'git-call-process-env buffer env args)
+ (message "Running git %s...done" (car args)))
+
+(defun git-run-command-region (buffer start end env &rest args)
+ "Run a git command with specified buffer region as input."
+ (message "Running git %s..." (car args))
+ (unless (eq 0 (if env
+ (git-run-process-region
+ buffer start end "env"
+ (append (git-get-env-strings env) (list "git") args))
+ (git-run-process-region
+ buffer start end "git" args)))
+ (error "Failed to run \"git %s\":\n%s" (mapconcat (lambda (x) x) args " ") (buffer-string)))
+ (message "Running git %s...done" (car args)))
+
+(defun git-get-string-sha1 (string)
+ "Read a SHA1 from the specified string."
+ (let ((pos (string-match "[0-9a-f]\\{40\\}" string)))
+ (and pos (substring string pos (match-end 0)))))
+
+(defun git-get-committer-name ()
+ "Return the name to use as GIT_COMMITTER_NAME."
+ ; copied from log-edit
+ (or git-committer-name
+ (and (boundp 'add-log-full-name) add-log-full-name)
+ (and (fboundp 'user-full-name) (user-full-name))
+ (and (boundp 'user-full-name) user-full-name)))
+
+(defun git-get-committer-email ()
+ "Return the email address to use as GIT_COMMITTER_EMAIL."
+ ; copied from log-edit
+ (or git-committer-email
+ (and (boundp 'add-log-mailing-address) add-log-mailing-address)
+ (and (fboundp 'user-mail-address) (user-mail-address))
+ (and (boundp 'user-mail-address) user-mail-address)))
+
+(defun git-escape-file-name (name)
+ "Escape a file name if necessary."
+ (if (string-match "[\n\t\"\\]" name)
+ (concat "\""
+ (mapconcat (lambda (c)
+ (case c
+ (?\n "\\n")
+ (?\t "\\t")
+ (?\\ "\\\\")
+ (?\" "\\\"")
+ (t (char-to-string c))))
+ name "")
+ "\"")
+ name))
+
+(defun git-get-top-dir (dir)
+ "Retrieve the top-level directory of a git tree."
+ (let ((cdup (with-output-to-string
+ (with-current-buffer standard-output
+ (cd dir)
+ (unless (eq 0 (call-process "git" nil t nil "rev-parse" "--show-cdup"))
+ (error "cannot find top-level git tree for %s." dir))))))
+ (expand-file-name (concat (file-name-as-directory dir)
+ (car (split-string cdup "\n"))))))
+
+;stolen from pcl-cvs
+(defun git-append-to-ignore (file)
+ "Add a file name to the ignore file in its directory."
+ (let* ((fullname (expand-file-name file))
+ (dir (file-name-directory fullname))
+ (name (file-name-nondirectory fullname)))
+ (save-window-excursion
+ (set-buffer (find-file-noselect (expand-file-name git-per-dir-ignore-file dir)))
+ (goto-char (point-max))
+ (unless (zerop (current-column)) (insert "\n"))
+ (insert name "\n")
+ (sort-lines nil (point-min) (point-max))
+ (save-buffer))))
+
+
+;;;; Wrappers for basic git commands
+;;;; ------------------------------------------------------------
+
+(defun git-rev-parse (rev)
+ "Parse a revision name and return its SHA1."
+ (git-get-string-sha1
+ (with-output-to-string
+ (with-current-buffer standard-output
+ (git-call-process-env t nil "rev-parse" rev)))))
+
+(defun git-symbolic-ref (ref)
+ "Wrapper for the git-symbolic-ref command."
+ (car
+ (split-string
+ (with-output-to-string
+ (with-current-buffer standard-output
+ (git-call-process-env t nil "symbolic-ref" ref)))
+ "\n")))
+
+(defun git-update-ref (ref val &optional oldval)
+ "Update a reference by calling git-update-ref."
+ (apply #'git-call-process-env nil nil "update-ref" ref val (if oldval (list oldval))))
+
+(defun git-read-tree (tree &optional index-file)
+ "Read a tree into the index file."
+ (apply #'git-call-process-env nil
+ (if index-file `(("GIT_INDEX_FILE" . ,index-file)) nil)
+ "read-tree" (if tree (list tree))))
+
+(defun git-write-tree (&optional index-file)
+ "Call git-write-tree and return the resulting tree SHA1 as a string."
+ (git-get-string-sha1
+ (with-output-to-string
+ (with-current-buffer standard-output
+ (git-call-process-env t
+ (if index-file `(("GIT_INDEX_FILE" . ,index-file)) nil)
+ "write-tree")))))
+
+(defun git-commit-tree (buffer tree head)
+ "Call git-commit-tree with buffer as input and return the resulting commit SHA1."
+ (let ((author-name (git-get-committer-name))
+ (author-email (git-get-committer-email))
+ author-date log-start log-end args)
+ (when head
+ (push "-p" args)
+ (push head args))
+ (with-current-buffer buffer
+ (goto-char (point-min))
+ (if
+ (setq log-start (re-search-forward (concat "^" git-log-msg-separator "\n") nil t))
+ (save-restriction
+ (narrow-to-region (point-min) log-start)
+ (goto-char (point-min))
+ (when (re-search-forward "^Author: +\\(.*?\\) *<\\(.*\\)> *$" nil t)
+ (setq author-name (match-string 1)
+ author-email (match-string 2)))
+ (goto-char (point-min))
+ (when (re-search-forward "^Date: +\\(.*\\)$" nil t)
+ (setq author-date (match-string 1)))
+ (goto-char (point-min))
+ (while (re-search-forward "^Parent: +\\([0-9a-f]+\\)" nil t)
+ (unless (string-equal head (match-string 1))
+ (push "-p" args)
+ (push (match-string 1) args))))
+ (setq log-start (point-min)))
+ (setq log-end (point-max)))
+ (git-get-string-sha1
+ (with-output-to-string
+ (with-current-buffer standard-output
+ (let ((coding-system-for-write git-commits-coding-system)
+ (env `(("GIT_AUTHOR_NAME" . ,author-name)
+ ("GIT_AUTHOR_EMAIL" . ,author-email)
+ ("GIT_COMMITTER_NAME" . ,(git-get-committer-name))
+ ("GIT_COMMITTER_EMAIL" . ,(git-get-committer-email)))))
+ (when author-date (push `("GIT_AUTHOR_DATE" . ,author-date) env))
+ (apply #'git-run-command-region
+ buffer log-start log-end env
+ "commit-tree" tree (nreverse args))))))))
+
+(defun git-empty-db-p ()
+ "Check if the git db is empty (no commit done yet)."
+ (not (eq 0 (call-process "git" nil nil nil "rev-parse" "--verify" "HEAD"))))
+
+(defun git-get-merge-heads ()
+ "Retrieve the merge heads from the MERGE_HEAD file if present."
+ (let (heads)
+ (when (file-readable-p ".git/MERGE_HEAD")
+ (with-temp-buffer
+ (insert-file-contents ".git/MERGE_HEAD" nil nil nil t)
+ (goto-char (point-min))
+ (while (re-search-forward "[0-9a-f]\\{40\\}" nil t)
+ (push (match-string 0) heads))))
+ (nreverse heads)))
+
+;;;; File info structure
+;;;; ------------------------------------------------------------
+
+; fileinfo structure stolen from pcl-cvs
+(defstruct (git-fileinfo
+ (:copier nil)
+ (:constructor git-create-fileinfo (state name &optional old-perm new-perm rename-state orig-name marked))
+ (:conc-name git-fileinfo->))
+ marked ;; t/nil
+ state ;; current state
+ name ;; file name
+ old-perm new-perm ;; permission flags
+ rename-state ;; rename or copy state
+ orig-name ;; original name for renames or copies
+ needs-refresh) ;; whether file needs to be refreshed
+
+(defvar git-status nil)
+
+(defun git-clear-status (status)
+ "Remove everything from the status list."
+ (ewoc-filter status (lambda (info) nil)))
+
+(defun git-set-files-state (files state)
+ "Set the state of a list of files."
+ (dolist (info files)
+ (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))))
+
+(defun git-state-code (code)
+ "Convert from a string to a added/deleted/modified state."
+ (case (string-to-char code)
+ (?M 'modified)
+ (?? 'unknown)
+ (?A 'added)
+ (?D 'deleted)
+ (?U 'unmerged)
+ (t nil)))
+
+(defun git-status-code-as-string (code)
+ "Format a git status code as string."
+ (case code
+ ('modified (propertize "Modified" 'face 'git-status-face))
+ ('unknown (propertize "Unknown " 'face 'git-unknown-face))
+ ('added (propertize "Added " 'face 'git-status-face))
+ ('deleted (propertize "Deleted " 'face 'git-status-face))
+ ('unmerged (propertize "Unmerged" 'face 'git-unmerged-face))
+ ('uptodate (propertize "Uptodate" 'face 'git-uptodate-face))
+ ('ignored (propertize "Ignored " 'face 'git-ignored-face))
+ (t "? ")))
+
+(defun git-rename-as-string (info)
+ "Return a string describing the copy or rename associated with INFO, or an empty string if none."
+ (let ((state (git-fileinfo->rename-state info)))
+ (if state
+ (propertize
+ (concat " ("
+ (if (eq state 'copy) "copied from "
+ (if (eq (git-fileinfo->state info) 'added) "renamed to "
+ "renamed from "))
+ (git-escape-file-name (git-fileinfo->orig-name info))
+ ")") 'face 'git-status-face)
+ "")))
+
+(defun git-permissions-as-string (old-perm new-perm)
+ "Format a permission change as string."
+ (propertize
+ (if (or (not old-perm)
+ (not new-perm)
+ (eq 0 (logand #O111 (logxor old-perm new-perm))))
+ " "
+ (if (eq 0 (logand #O111 old-perm)) "+x" "-x"))
+ 'face 'git-permission-face))
+
+(defun git-fileinfo-prettyprint (info)
+ "Pretty-printer for the git-fileinfo structure."
+ (insert (format " %s %s %s %s%s"
+ (if (git-fileinfo->marked info) (propertize "*" 'face 'git-mark-face) " ")
+ (git-status-code-as-string (git-fileinfo->state info))
+ (git-permissions-as-string (git-fileinfo->old-perm info) (git-fileinfo->new-perm info))
+ (git-escape-file-name (git-fileinfo->name info))
+ (git-rename-as-string info))))
+
+(defun git-parse-status (status)
+ "Parse the output of git-diff-index in the current buffer."
+ (goto-char (point-min))
+ (while (re-search-forward
+ ":\\([0-7]\\{6\\}\\) \\([0-7]\\{6\\}\\) [0-9a-f]\\{40\\} [0-9a-f]\\{40\\} \\(\\([ADMU]\\)\0\\([^\0]+\\)\\|\\([CR]\\)[0-9]*\0\\([^\0]+\\)\0\\([^\0]+\\)\\)\0"
+ nil t 1)
+ (let ((old-perm (string-to-number (match-string 1) 8))
+ (new-perm (string-to-number (match-string 2) 8))
+ (state (or (match-string 4) (match-string 6)))
+ (name (or (match-string 5) (match-string 7)))
+ (new-name (match-string 8)))
+ (if new-name ; copy or rename
+ (if (eq ?C (string-to-char state))
+ (ewoc-enter-last status (git-create-fileinfo 'added new-name old-perm new-perm 'copy name))
+ (ewoc-enter-last status (git-create-fileinfo 'deleted name 0 0 'rename new-name))
+ (ewoc-enter-last status (git-create-fileinfo 'added new-name old-perm new-perm 'rename name)))
+ (ewoc-enter-last status (git-create-fileinfo (git-state-code state) name old-perm new-perm))))))
+
+(defun git-find-status-file (status file)
+ "Find a given file in the status ewoc and return its node."
+ (let ((node (ewoc-nth status 0)))
+ (while (and node (not (string= file (git-fileinfo->name (ewoc-data node)))))
+ (setq node (ewoc-next status node)))
+ node))
+
+(defun git-parse-ls-files (status default-state &optional skip-existing)
+ "Parse the output of git-ls-files in the current buffer."
+ (goto-char (point-min))
+ (let (infolist)
+ (while (re-search-forward "\\([HMRCK?]\\) \\([^\0]*\\)\0" nil t 1)
+ (let ((state (match-string 1))
+ (name (match-string 2)))
+ (unless (and skip-existing (git-find-status-file status name))
+ (push (git-create-fileinfo (or (git-state-code state) default-state) name) infolist))))
+ (dolist (info (nreverse infolist))
+ (ewoc-enter-last status info))))
+
+(defun git-parse-ls-unmerged (status)
+ "Parse the output of git-ls-files -u in the current buffer."
+ (goto-char (point-min))
+ (let (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) files))))
+ (git-set-files-state files 'unmerged)))
+
+(defun git-add-status-file (state name)
+ "Add a new file to the status list (if not existing already) and return its node."
+ (unless git-status (error "Not in git-status buffer."))
+ (or (git-find-status-file git-status name)
+ (ewoc-enter-last git-status (git-create-fileinfo state name))))
+
+(defun git-marked-files ()
+ "Return a list of all marked files, or if none a list containing just the file at cursor position."
+ (unless git-status (error "Not in git-status buffer."))
+ (or (ewoc-collect git-status (lambda (info) (git-fileinfo->marked info)))
+ (list (ewoc-data (ewoc-locate git-status)))))
+
+(defun git-marked-files-state (&rest states)
+ "Return marked files that are in the specified states."
+ (let ((files (git-marked-files))
+ result)
+ (dolist (info files)
+ (when (memq (git-fileinfo->state info) states)
+ (push info result)))
+ result))
+
+(defun git-refresh-files ()
+ "Refresh all files that need it and clear the needs-refresh flag."
+ (unless git-status (error "Not in git-status buffer."))
+ (ewoc-map
+ (lambda (info)
+ (let ((refresh (git-fileinfo->needs-refresh info)))
+ (setf (git-fileinfo->needs-refresh info) nil)
+ refresh))
+ git-status)
+ ; move back to goal column
+ (when goal-column (move-to-column goal-column)))
+
+(defun git-refresh-ewoc-hf (status)
+ "Refresh the ewoc header and footer."
+ (let ((branch (git-symbolic-ref "HEAD"))
+ (head (if (git-empty-db-p) "Nothing committed yet"
+ (substring (git-rev-parse "HEAD") 0 10)))
+ (merge-heads (git-get-merge-heads)))
+ (ewoc-set-hf status
+ (format "Directory: %s\nBranch: %s\nHead: %s%s\n"
+ default-directory
+ (if (string-match "^refs/heads/" branch)
+ (substring branch (match-end 0))
+ branch)
+ head
+ (if merge-heads
+ (concat "\nMerging: "
+ (mapconcat (lambda (str) (substring str 0 10)) merge-heads " "))
+ ""))
+ (if (ewoc-nth status 0) "" " No changes."))))
+
+(defun git-get-filenames (files)
+ (mapcar (lambda (info) (git-fileinfo->name info)) files))
+
+(defun git-update-index (index-file files)
+ "Run git-update-index on a list of files."
+ (let ((env (and index-file `(("GIT_INDEX_FILE" . ,index-file))))
+ added deleted modified)
+ (dolist (info files)
+ (case (git-fileinfo->state info)
+ ('added (push info added))
+ ('deleted (push info deleted))
+ ('modified (push info modified))))
+ (when added
+ (apply #'git-run-command nil env "update-index" "--add" "--" (git-get-filenames added)))
+ (when deleted
+ (apply #'git-run-command nil env "update-index" "--remove" "--" (git-get-filenames deleted)))
+ (when modified
+ (apply #'git-run-command nil env "update-index" "--" (git-get-filenames modified)))))
+
+(defun git-do-commit ()
+ "Perform the actual commit using the current buffer as log message."
+ (interactive)
+ (let ((buffer (current-buffer))
+ (index-file (make-temp-file "gitidx")))
+ (with-current-buffer log-edit-parent-buffer
+ (if (git-marked-files-state 'unmerged)
+ (message "You cannot commit unmerged files, resolve them first.")
+ (unwind-protect
+ (let ((files (git-marked-files-state 'added 'deleted 'modified))
+ head head-tree)
+ (unless (git-empty-db-p)
+ (setq head (git-rev-parse "HEAD")
+ head-tree (git-rev-parse "HEAD^{tree}")))
+ (if files
+ (progn
+ (git-read-tree head-tree index-file)
+ (git-update-index nil files) ;update both the default index
+ (git-update-index index-file files) ;and the temporary one
+ (let ((tree (git-write-tree index-file)))
+ (if (or (not (string-equal tree head-tree))
+ (yes-or-no-p "The tree was not modified, do you really want to perform an empty commit? "))
+ (let ((commit (git-commit-tree buffer tree head)))
+ (git-update-ref "HEAD" commit head)
+ (condition-case nil (delete-file ".git/MERGE_HEAD") (error nil))
+ (with-current-buffer buffer (erase-buffer))
+ (git-set-files-state files 'uptodate)
+ (git-refresh-files)
+ (git-refresh-ewoc-hf git-status)
+ (message "Committed %s." commit))
+ (message "Commit aborted."))))
+ (message "No files to commit.")))
+ (delete-file index-file))))))
+
+
+;;;; Interactive functions
+;;;; ------------------------------------------------------------
+
+(defun git-mark-file ()
+ "Mark the file that the cursor is on and move to the next one."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (let* ((pos (ewoc-locate git-status))
+ (info (ewoc-data pos)))
+ (setf (git-fileinfo->marked info) t)
+ (ewoc-invalidate git-status pos)
+ (ewoc-goto-next git-status 1)))
+
+(defun git-unmark-file ()
+ "Unmark the file that the cursor is on and move to the next one."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (let* ((pos (ewoc-locate git-status))
+ (info (ewoc-data pos)))
+ (setf (git-fileinfo->marked info) nil)
+ (ewoc-invalidate git-status pos)
+ (ewoc-goto-next git-status 1)))
+
+(defun git-unmark-file-up ()
+ "Unmark the file that the cursor is on and move to the previous one."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (let* ((pos (ewoc-locate git-status))
+ (info (ewoc-data pos)))
+ (setf (git-fileinfo->marked info) nil)
+ (ewoc-invalidate git-status pos)
+ (ewoc-goto-prev git-status 1)))
+
+(defun git-mark-all ()
+ "Mark all files."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (ewoc-map (lambda (info) (setf (git-fileinfo->marked info) t) t) git-status)
+ ; move back to goal column after invalidate
+ (when goal-column (move-to-column goal-column)))
+
+(defun git-unmark-all ()
+ "Unmark all files."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (ewoc-map (lambda (info) (setf (git-fileinfo->marked info) nil) t) git-status)
+ ; move back to goal column after invalidate
+ (when goal-column (move-to-column goal-column)))
+
+(defun git-toggle-all-marks ()
+ "Toggle all file marks."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (ewoc-map (lambda (info) (setf (git-fileinfo->marked info) (not (git-fileinfo->marked info))) t) git-status)
+ ; move back to goal column after invalidate
+ (when goal-column (move-to-column goal-column)))
+
+(defun git-next-file (&optional n)
+ "Move the selection down N files."
+ (interactive "p")
+ (unless git-status (error "Not in git-status buffer."))
+ (ewoc-goto-next git-status n))
+
+(defun git-prev-file (&optional n)
+ "Move the selection up N files."
+ (interactive "p")
+ (unless git-status (error "Not in git-status buffer."))
+ (ewoc-goto-prev git-status n))
+
+(defun git-add-file ()
+ "Add marked file(s) to the index cache."
+ (interactive)
+ (let ((files (git-marked-files-state 'unknown)))
+ (unless files
+ (push (ewoc-data
+ (git-add-status-file 'added (file-relative-name
+ (read-file-name "File to add: " nil nil t))))
+ files))
+ (apply #'git-run-command nil nil "update-index" "--info-only" "--add" "--" (git-get-filenames files))
+ (git-set-files-state files 'added)
+ (git-refresh-files)))
+
+(defun git-ignore-file ()
+ "Add marked file(s) to the ignore list."
+ (interactive)
+ (let ((files (git-marked-files-state 'unknown)))
+ (unless files
+ (push (ewoc-data
+ (git-add-status-file 'unknown (file-relative-name
+ (read-file-name "File to ignore: " nil nil t))))
+ files))
+ (dolist (info files) (git-append-to-ignore (git-fileinfo->name info)))
+ (git-set-files-state files 'ignored)
+ (git-refresh-files)))
+
+(defun git-remove-file ()
+ "Remove the marked file(s)."
+ (interactive)
+ (let ((files (git-marked-files-state 'added 'modified 'unknown 'uptodate)))
+ (unless files
+ (push (ewoc-data
+ (git-add-status-file 'unknown (file-relative-name
+ (read-file-name "File to remove: " nil nil t))))
+ files))
+ (if (yes-or-no-p
+ (format "Remove %d file%s? " (length files) (if (> (length files) 1) "s" "")))
+ (progn
+ (dolist (info files)
+ (let ((name (git-fileinfo->name info)))
+ (when (file-exists-p name) (delete-file name))))
+ (apply #'git-run-command nil nil "update-index" "--info-only" "--remove" "--" (git-get-filenames files))
+ ; remove unknown files from the list, set the others to deleted
+ (ewoc-filter git-status
+ (lambda (info files)
+ (not (and (memq info files) (eq (git-fileinfo->state info) 'unknown))))
+ files)
+ (git-set-files-state files 'deleted)
+ (git-refresh-files)
+ (unless (ewoc-nth git-status 0) ; refresh header if list is empty
+ (git-refresh-ewoc-hf git-status)))
+ (message "Aborting"))))
+
+(defun git-revert-file ()
+ "Revert changes to the marked file(s)."
+ (interactive)
+ (let ((files (git-marked-files))
+ added modified)
+ (when (and files
+ (yes-or-no-p
+ (format "Revert %d file%s? " (length files) (if (> (length files) 1) "s" ""))))
+ (dolist (info files)
+ (case (git-fileinfo->state info)
+ ('added (push info added))
+ ('deleted (push info modified))
+ ('unmerged (push info modified))
+ ('modified (push info modified))))
+ (when added
+ (apply #'git-run-command nil nil "update-index" "--force-remove" "--" (git-get-filenames added))
+ (git-set-files-state added 'unknown))
+ (when modified
+ (apply #'git-run-command nil nil "checkout" "HEAD" (git-get-filenames modified))
+ (git-set-files-state modified 'uptodate))
+ (git-refresh-files))))
+
+(defun git-resolve-file ()
+ "Resolve conflicts in marked file(s)."
+ (interactive)
+ (let ((files (git-marked-files-state 'unmerged)))
+ (when files
+ (apply #'git-run-command nil nil "update-index" "--info-only" "--" (git-get-filenames files))
+ (git-set-files-state files 'modified)
+ (git-refresh-files))))
+
+(defun git-remove-handled ()
+ "Remove handled files from the status list."
+ (interactive)
+ (ewoc-filter git-status
+ (lambda (info)
+ (not (or (eq (git-fileinfo->state info) 'ignored)
+ (eq (git-fileinfo->state info) 'uptodate)))))
+ (unless (ewoc-nth git-status 0) ; refresh header if list is empty
+ (git-refresh-ewoc-hf git-status)))
+
+(defun git-setup-diff-buffer (buffer)
+ "Setup a buffer for displaying a diff."
+ (with-current-buffer buffer
+ (diff-mode)
+ (goto-char (point-min))
+ (setq buffer-read-only t))
+ (display-buffer buffer)
+ (shrink-window-if-larger-than-buffer))
+
+(defun git-diff-file ()
+ "Diff the marked file(s) against HEAD."
+ (interactive)
+ (let ((files (git-marked-files)))
+ (git-setup-diff-buffer
+ (apply #'git-run-command-buffer "*git-diff*" "diff-index" "-p" "-M" "HEAD" "--" (git-get-filenames files)))))
+
+(defun git-diff-unmerged-file (stage)
+ "Diff the marked unmerged file(s) against the specified stage."
+ (let ((files (git-marked-files)))
+ (git-setup-diff-buffer
+ (apply #'git-run-command-buffer "*git-diff*" "diff-files" "-p" stage "--" (git-get-filenames files)))))
+
+(defun git-diff-file-base ()
+ "Diff the marked unmerged file(s) against the common base file."
+ (interactive)
+ (git-diff-unmerged-file "-1"))
+
+(defun git-diff-file-mine ()
+ "Diff the marked unmerged file(s) against my pre-merge version."
+ (interactive)
+ (git-diff-unmerged-file "-2"))
+
+(defun git-diff-file-other ()
+ "Diff the marked unmerged file(s) against the other's pre-merge version."
+ (interactive)
+ (git-diff-unmerged-file "-3"))
+
+(defun git-diff-file-combined ()
+ "Do a combined diff of the marked unmerged file(s)."
+ (interactive)
+ (git-diff-unmerged-file "-c"))
+
+(defun git-diff-file-idiff ()
+ "Perform an interactive diff on the current file."
+ (interactive)
+ (error "Interactive diffs not implemented yet."))
+
+(defun git-log-file ()
+ "Display a log of changes to the marked file(s)."
+ (interactive)
+ (let* ((files (git-marked-files))
+ (coding-system-for-read git-commits-coding-system)
+ (buffer (apply #'git-run-command-buffer "*git-log*" "rev-list" "--pretty" "HEAD" "--" (git-get-filenames files))))
+ (with-current-buffer buffer
+ ; (git-log-mode) FIXME: implement log mode
+ (goto-char (point-min))
+ (setq buffer-read-only t))
+ (display-buffer buffer)))
+
+(defun git-log-edit-files ()
+ "Return a list of marked files for use in the log-edit buffer."
+ (with-current-buffer log-edit-parent-buffer
+ (git-get-filenames (git-marked-files-state 'added 'deleted 'modified))))
+
+(defun git-commit-file ()
+ "Commit the marked file(s), asking for a commit message."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (let ((buffer (get-buffer-create "*git-commit*"))
+ (merge-heads (git-get-merge-heads))
+ (dir default-directory))
+ (with-current-buffer buffer
+ (when (eq 0 (buffer-size))
+ (cd dir)
+ (erase-buffer)
+ (insert
+ (propertize
+ (format "Author: %s <%s>\n%s"
+ (git-get-committer-name) (git-get-committer-email)
+ (if merge-heads
+ (format "Parent: %s\n%s\n"
+ (git-rev-parse "HEAD")
+ (mapconcat (lambda (str) (concat "Parent: " str)) merge-heads "\n"))
+ ""))
+ 'face 'git-header-face)
+ (propertize git-log-msg-separator 'face 'git-separator-face)
+ "\n")
+ (when (and merge-heads (file-readable-p ".git/MERGE_MSG"))
+ (insert-file-contents ".git/MERGE_MSG"))))
+ (log-edit #'git-do-commit nil #'git-log-edit-files buffer)))
+
+(defun git-find-file ()
+ "Visit the current file in its own buffer."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (let ((info (ewoc-data (ewoc-locate git-status))))
+ (find-file (git-fileinfo->name info))
+ (when (eq 'unmerged (git-fileinfo->state info))
+ (smerge-mode))))
+
+(defun git-find-file-imerge ()
+ "Visit the current file in interactive merge mode."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (let ((info (ewoc-data (ewoc-locate git-status))))
+ (find-file (git-fileinfo->name info))
+ (smerge-ediff)))
+
+(defun git-view-file ()
+ "View the current file in its own buffer."
+ (interactive)
+ (unless git-status (error "Not in git-status buffer."))
+ (let ((info (ewoc-data (ewoc-locate git-status))))
+ (view-file (git-fileinfo->name info))))
+
+(defun git-refresh-status ()
+ "Refresh the git status buffer."
+ (interactive)
+ (let* ((status git-status)
+ (pos (ewoc-locate status))
+ (cur-name (and pos (git-fileinfo->name (ewoc-data pos)))))
+ (unless status (error "Not in git-status buffer."))
+ (git-clear-status status)
+ (git-run-command nil nil "update-index" "--info-only" "--refresh")
+ (if (git-empty-db-p)
+ ; we need some special handling for an empty db
+ (with-temp-buffer
+ (git-run-command t nil "ls-files" "-z" "-t" "-c")
+ (git-parse-ls-files status 'added))
+ (with-temp-buffer
+ (git-run-command t nil "diff-index" "-z" "-M" "HEAD")
+ (git-parse-status status)))
+ (with-temp-buffer
+ (git-run-command t nil "ls-files" "-z" "-u")
+ (git-parse-ls-unmerged status))
+ (when (file-readable-p ".git/info/exclude")
+ (with-temp-buffer
+ (git-run-command t nil "ls-files" "-z" "-t" "-o"
+ "--exclude-from=.git/info/exclude"
+ (concat "--exclude-per-directory=" git-per-dir-ignore-file))
+ (git-parse-ls-files status 'unknown)))
+ (git-refresh-files)
+ (git-refresh-ewoc-hf status)
+ ; move point to the current file name if any
+ (let ((node (and cur-name (git-find-status-file status cur-name))))
+ (when node (ewoc-goto-node status node)))))
+
+(defun git-status-quit ()
+ "Quit git-status mode."
+ (interactive)
+ (bury-buffer))
+
+;;;; Major Mode
+;;;; ------------------------------------------------------------
+
+(defvar git-status-mode-hook nil
+ "Run after `git-status-mode' is setup.")
+
+(defvar git-status-mode-map nil
+ "Keymap for git major mode.")
+
+(defvar git-status nil
+ "List of all files managed by the git-status mode.")
+
+(unless git-status-mode-map
+ (let ((map (make-keymap))
+ (diff-map (make-sparse-keymap)))
+ (suppress-keymap map)
+ (define-key map " " 'git-next-file)
+ (define-key map "a" 'git-add-file)
+ (define-key map "c" 'git-commit-file)
+ (define-key map "d" diff-map)
+ (define-key map "=" 'git-diff-file)
+ (define-key map "f" 'git-find-file)
+ (define-key map [RET] 'git-find-file)
+ (define-key map "g" 'git-refresh-status)
+ (define-key map "i" 'git-ignore-file)
+ (define-key map "l" 'git-log-file)
+ (define-key map "m" 'git-mark-file)
+ (define-key map "M" 'git-mark-all)
+ (define-key map "n" 'git-next-file)
+ (define-key map "p" 'git-prev-file)
+ (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" 'git-toggle-all-marks)
+ (define-key map "u" 'git-unmark-file)
+ (define-key map "U" 'git-revert-file)
+ (define-key map "v" 'git-view-file)
+ (define-key map "x" 'git-remove-handled)
+ (define-key map "\C-?" 'git-unmark-file-up)
+ (define-key map "\M-\C-?" 'git-unmark-all)
+ ; the diff submap
+ (define-key diff-map "b" 'git-diff-file-base)
+ (define-key diff-map "c" 'git-diff-file-combined)
+ (define-key diff-map "=" 'git-diff-file)
+ (define-key diff-map "e" 'git-diff-file-idiff)
+ (define-key diff-map "E" 'git-find-file-imerge)
+ (define-key diff-map "m" 'git-diff-file-mine)
+ (define-key diff-map "o" 'git-diff-file-other)
+ (setq git-status-mode-map map)))
+
+;; git mode should only run in the *git status* buffer
+(put 'git-status-mode 'mode-class 'special)
+
+(defun git-status-mode ()
+ "Major mode for interacting with Git.
+Commands:
+\\{git-status-mode-map}"
+ (kill-all-local-variables)
+ (buffer-disable-undo)
+ (setq mode-name "git status"
+ major-mode 'git-status-mode
+ goal-column 17
+ buffer-read-only t)
+ (use-local-map git-status-mode-map)
+ (let ((buffer-read-only nil))
+ (erase-buffer)
+ (let ((status (ewoc-create 'git-fileinfo-prettyprint "" "")))
+ (set (make-local-variable 'git-status) status))
+ (run-hooks 'git-status-mode-hook)))
+
+(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))))
+ (switch-to-buffer buffer)
+ (git-status-mode)
+ (cd dir)
+ (git-refresh-status)
+ (goto-char (point-min)))
+ (message "%s is not a git working tree." dir)))
+
+(provide 'git)
+;;; git.el ends here
--
1.2.1.gfd1fe
--
Alexandre Julliard
julliard@winehq.org
^ permalink raw reply related
* [PATCH] Nice error message for empty idents
From: Petr Baudis @ 2006-02-18 17:27 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vzmkpqco1.fsf@assigned-by-dhcp.cox.net>
Dear diary, on Sat, Feb 18, 2006 at 09:44:14AM CET, I got a letter
where Junio C Hamano <junkio@cox.net> said that...
> It appears that some people who did not care about having bogus
> names in their own commit messages are bitten by the recent
> change to require a sane environment [*1*].
>
> While it was a good idea to prevent people from using bogus
> names to create commits and doing sign-offs, the error message
> is not very informative. This patch attempts to warn things
> upfront and hint people how to fix their environments.
>
> Likes, dislikes, don't cares?
One dislike from me - you shouldn't care if you ain't gonna do it - it
makes no sense to require valid gecos if you are never committing
anything. Note that this "premature requirement" plague has already hit
GIT - come on:
$ git-rev-list --help
fatal: Not a git repository
That's worse than CVS (which allows cvs --help cmd but not cvs cmd
--help outside of a repository).
I agree that the error message itself is bad.
---
[PATCH] Nice error message for empty idents
Signed-off-by: Petr Baudis <pasky@suse.cz>
---
commit 19b5bda8f0301ed4b856c5cd9137637b89d95d30
tree 8f91bfd101c32f258c3d8cca467eb7be26d62b91
parent 8dcc626cd144b2c6eae2a299242bbbe905cb0059
author Petr Baudis <pasky@suse.cz> Sat, 18 Feb 2006 18:26:32 +0100
committer Petr Baudis <xpasky@machine.or.cz> Sat, 18 Feb 2006 18:26:32 +0100
ident.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/ident.c b/ident.c
index 23b8cfc..c57ba5c 100644
--- a/ident.c
+++ b/ident.c
@@ -168,9 +168,10 @@ static const char *get_ident(const char
if (!email)
email = git_default_email;
- if (!*name || !*email)
- die("empty ident %s <%s> not allowed",
- name, email);
+ if (!*name)
+ die("empty realname not allowed - please set a realname for your login or use GIT_AUTHOR_NAME");
+ if (!*email)
+ die("empty email not allowed - please set your GIT_AUTHOR_EMAIL to a non-empty value");
strcpy(date, git_default_date);
if (date_str)
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Of the 3 great composers Mozart tells us what it's like to be human,
Beethoven tells us what it's like to be Beethoven and Bach tells us
what it's like to be the universe. -- Douglas Adams
^ permalink raw reply related
* Re: git-cvs-import retries
From: Junio C Hamano @ 2006-02-18 18:42 UTC (permalink / raw)
To: Martin Mares; +Cc: git
In-Reply-To: <mj+md-20060218.130645.5680.albireo@ucw.cz>
Martin Mares <mj@ucw.cz> writes:
> But it did and I finally understand why: _line() can exit not only
> by return, but also by falling over when readline() returns undef.
Ah, you are right and I feel stupid. It's been a while since I
wrote real Perl code the last time, and forgot that "the last
evaluation" rule when I was reading the code.
It did not help that one of the languages I use in my day-job
(which I am too ashamed to even name) uses "if fell off at the
end return undef" rule X-<.
^ permalink raw reply
* Re: [PATCH] Nice error message for empty idents
From: Junio C Hamano @ 2006-02-18 18:55 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
In-Reply-To: <20060218172731.GV31278@pasky.or.cz>
Petr Baudis <pasky@suse.cz> writes:
> $ git-rev-list --help
> fatal: Not a git repository
Hmph, true. Ideas?
> I agree that the error message itself is bad.
> - if (!*name || !*email)
> - die("empty ident %s <%s> not allowed",
> - name, email);
> + if (!*name)
> + die("empty realname not allowed - please set a realname for your login or use GIT_AUTHOR_NAME");
> + if (!*email)
> + die("empty email not allowed - please set your GIT_AUTHOR_EMAIL to a non-empty value");
I've considered doing this, but didn't do it that way, because I
could not figure out what to do with GIT_COMMITTER_NAME. Also
it might make sense to suggest user.name configuration item in
the error/help message. Ideas?
^ permalink raw reply
* [PATCH] Fix retries in git-cvsimport
From: Martin Mares @ 2006-02-18 20:44 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvevco6e3.fsf@assigned-by-dhcp.cox.net>
Fixed a couple of bugs in recovering from broken connections:
The _line() method now returns undef correctly when the connection
is broken instead of falling off the function and returning garbage.
Retries are now reported to stderr and the eventual partially
downloaded file is discarded instead of being appended to.
The "Server gone away" test has been removed, because it was
reachable only if the garbage return bug bit.
Signed-Off-By: Martin Mares <mj@ucw.cz>
--- old/git-cvsimport 2006-02-17 13:02:24.000000000 +0100
+++ new/git-cvsimport 2006-02-18 14:16:33.000000000 +0100
@@ -361,6 +361,7 @@
}
}
}
+ return undef;
}
sub file {
my($self,$fn,$rev) = @_;
@@ -372,19 +373,15 @@
$self->_file($fn,$rev) and $res = $self->_line($fh);
if (!defined $res) {
- # retry
+ print STDERR "Server has gone away while fetching $fn $rev, retrying...\n";
+ truncate $fh, 0;
$self->conn();
- $self->_file($fn,$rev)
- or die "No file command send\n";
+ $self->_file($fn,$rev) or die "No file command send";
$res = $self->_line($fh);
- die "No input: $fn $rev\n" unless defined $res;
+ die "Retry failed" unless defined $res;
}
close ($fh);
- if ($res eq '') {
- die "Looks like the server has gone away while fetching $fn $rev -- exiting!";
- }
-
return ($name, $res);
}
^ permalink raw reply
* gitk patch display corner-case bug
From: Karl Hasselström @ 2006-02-18 23:36 UTC (permalink / raw)
To: Paul Mackerras; +Cc: git
In a recently updated stgit tree,
$ git-diff 51cb39db\^ 51cb39db
diff --git a/templates/covermail.tmpl b/templates/covermail.tmpl
index 9789c9c..44cd19e 100644
--- a/templates/covermail.tmpl
+++ b/templates/covermail.tmpl
@@ -4,5 +4,5 @@ Date: %(date)s
%(endofheaders)s
The following series implements...
---
+--
Signature
That is, a trailing whitespace was added after the two dashes.
However, gitk displays this as
index 9789c9c..44cd19e 100644
@@ -2,7 +2,7 @@ From: %(maintainer)s
Subject: [PATCH%(version)s%(number)s] Series short description
Date: %(date)s
%(endofheaders)s
The following series implements...
+--
Signature
Totally correct except that it omitted the line consisting of only
three dashes.
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
^ permalink raw reply
* [PATCH] Delay "empty ident" errors until they really matter.
From: Junio C Hamano @ 2006-02-19 4:56 UTC (permalink / raw)
To: git; +Cc: Petr Baudis
In-Reply-To: <20060218172731.GV31278@pasky.or.cz>
Previous one warned people upfront to encourage fixing their
environment early, but some people just use repositories and git
tools read-only without making any changes, and in such a case
there is not much point insisting on them having a usable ident.
This round attempts to move the error until either "git-var"
asks for the ident explicitly or "commit-tree" wants to use it.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Petr Baudis <pasky@suse.cz> writes:
> One dislike from me - you shouldn't care if you ain't gonna do it - it
> makes no sense to require valid gecos if you are never committing
> anything.
You are absolutely right. This is to fix the previous one.
cache.h | 4 ++--
commit-tree.c | 4 ++--
ident.c | 47 +++++++++++++++++++++++++----------------------
var.c | 6 +++---
4 files changed, 32 insertions(+), 29 deletions(-)
749be728d469e9a0acfdc020feff17c2da510083
diff --git a/cache.h b/cache.h
index b5db01f..da73fb3 100644
--- a/cache.h
+++ b/cache.h
@@ -246,8 +246,8 @@ void datestamp(char *buf, int bufsize);
unsigned long approxidate(const char *);
extern int setup_ident(void);
-extern const char *git_author_info(void);
-extern const char *git_committer_info(void);
+extern const char *git_author_info(int);
+extern const char *git_committer_info(int);
struct checkout {
const char *base_dir;
diff --git a/commit-tree.c b/commit-tree.c
index b1c8dca..88871b0 100644
--- a/commit-tree.c
+++ b/commit-tree.c
@@ -118,8 +118,8 @@ int main(int argc, char **argv)
add_buffer(&buffer, &size, "parent %s\n", sha1_to_hex(parent_sha1[i]));
/* Person/date information */
- add_buffer(&buffer, &size, "author %s\n", git_author_info());
- add_buffer(&buffer, &size, "committer %s\n\n", git_committer_info());
+ add_buffer(&buffer, &size, "author %s\n", git_author_info(1));
+ add_buffer(&buffer, &size, "committer %s\n\n", git_committer_info(1));
/* And add the comment */
while (fgets(comment, sizeof(comment), stdin) != NULL)
diff --git a/ident.c b/ident.c
index 09d4d71..7c81fe8 100644
--- a/ident.c
+++ b/ident.c
@@ -46,15 +46,6 @@ static void copy_gecos(struct passwd *w,
}
-static const char au_env[] = "GIT_AUTHOR_NAME";
-static const char co_env[] = "GIT_COMMITTER_NAME";
-static const char env_hint[] =
-"\n*** Environment problem:\n"
-"*** Your name cannot be determined from your system services (gecos).\n"
-"*** You would need to set %s and %s\n"
-"*** environment variables; otherwise you won't be able to perform\n"
-"*** certain operations because of \"empty ident\" errors.\n\n";
-
int setup_ident(void)
{
int len;
@@ -66,11 +57,6 @@ int setup_ident(void)
/* Get the name ("gecos") */
copy_gecos(pw, git_default_name, sizeof(git_default_name));
- if (!*git_default_name) {
- if (!getenv(au_env) || !getenv(co_env))
- fprintf(stderr, env_hint, au_env, co_env);
- }
-
/* Make up a fake email address (name + '@' + hostname [+ '.' + domainname]) */
len = strlen(pw->pw_name);
if (len > sizeof(git_default_email)/2)
@@ -170,8 +156,18 @@ static int copy(char *buf, int size, int
return offset;
}
+static const char au_env[] = "GIT_AUTHOR_NAME";
+static const char co_env[] = "GIT_COMMITTER_NAME";
+static const char *env_hint =
+"\n*** Environment problem:\n"
+"*** Your name cannot be determined from your system services (gecos).\n"
+"*** You would need to set %s and %s\n"
+"*** environment variables; otherwise you won't be able to perform\n"
+"*** certain operations because of \"empty ident\" errors.\n"
+"*** Alternatively, you can use user.name configuration variable.\n\n";
+
static const char *get_ident(const char *name, const char *email,
- const char *date_str)
+ const char *date_str, int error_on_no_name)
{
static char buffer[1000];
char date[50];
@@ -182,9 +178,14 @@ static const char *get_ident(const char
if (!email)
email = git_default_email;
- if (!*name || !*email)
- die("empty ident %s <%s> not allowed",
- name, email);
+ if (!*name) {
+ if (name == git_default_name && env_hint) {
+ fprintf(stderr, env_hint, au_env, co_env);
+ env_hint = NULL; /* warn only once, for "git-var -l" */
+ }
+ if (error_on_no_name)
+ die("empty ident %s <%s> not allowed", name, email);
+ }
strcpy(date, git_default_date);
if (date_str)
@@ -201,16 +202,18 @@ static const char *get_ident(const char
return buffer;
}
-const char *git_author_info(void)
+const char *git_author_info(int error_on_no_name)
{
return get_ident(getenv("GIT_AUTHOR_NAME"),
getenv("GIT_AUTHOR_EMAIL"),
- getenv("GIT_AUTHOR_DATE"));
+ getenv("GIT_AUTHOR_DATE"),
+ error_on_no_name);
}
-const char *git_committer_info(void)
+const char *git_committer_info(int error_on_no_name)
{
return get_ident(getenv("GIT_COMMITTER_NAME"),
getenv("GIT_COMMITTER_EMAIL"),
- getenv("GIT_COMMITTER_DATE"));
+ getenv("GIT_COMMITTER_DATE"),
+ error_on_no_name);
}
diff --git a/var.c b/var.c
index 59da56d..a57a33b 100644
--- a/var.c
+++ b/var.c
@@ -12,7 +12,7 @@ static const char var_usage[] = "git-var
struct git_var {
const char *name;
- const char *(*read)(void);
+ const char *(*read)(int);
};
static struct git_var git_vars[] = {
{ "GIT_COMMITTER_IDENT", git_committer_info },
@@ -24,7 +24,7 @@ static void list_vars(void)
{
struct git_var *ptr;
for(ptr = git_vars; ptr->read; ptr++) {
- printf("%s=%s\n", ptr->name, ptr->read());
+ printf("%s=%s\n", ptr->name, ptr->read(0));
}
}
@@ -35,7 +35,7 @@ static const char *read_var(const char *
val = NULL;
for(ptr = git_vars; ptr->read; ptr++) {
if (strcmp(var, ptr->name) == 0) {
- val = ptr->read();
+ val = ptr->read(1);
break;
}
}
--
1.2.1.g2902
^ permalink raw reply related
* [PATCH] Keep Porcelainish from failing by broken ident after making changes.
From: Junio C Hamano @ 2006-02-19 4:59 UTC (permalink / raw)
To: git
"empty ident not allowed" error makes commit-tree fail, so we
are already safer in that we would not end up with commit
objects that have bogus names on the author or committer fields.
However, before commit-tree is called there are already changes
made to the index file and the working tree. The operation can
be resumed after fixing the environment problem, but when this
triggers to a newcomer with unusable gecos, the first question
becomes "what did I lose and how would I recover".
This patch modifies some Porcelainish commands to verify
GIT_COMMITTER_IDENT as soon as we know we are going to make some
commits before doing much damage to prevent confusion.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* This is a follow-up on the previous "delay empty ident" error
one. "git pull random-place" otherwise would confuse and
scare new users, even though what it leaves would often be a
perfectly fine committable state.
git-am.sh | 4 +++-
git-applymbox.sh | 2 ++
git-merge.sh | 5 +++++
git-resolve.sh | 3 +++
4 files changed, 13 insertions(+), 1 deletions(-)
e3b59a44f6705896db80965427a7cf9e2112634b
diff --git a/git-am.sh b/git-am.sh
index 98b9215..85ecada 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -1,11 +1,13 @@
#!/bin/sh
#
-#
+# Copyright (c) 2005, 2006 Junio C Hamano
USAGE='[--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way] <mbox>
or, when resuming [--skip | --resolved]'
. git-sh-setup
+git var GIT_COMMITTER_IDENT >/dev/null || exit
+
stop_here () {
echo "$1" >"$dotest/next"
exit 1
diff --git a/git-applymbox.sh b/git-applymbox.sh
index 61c8c02..5569fdc 100755
--- a/git-applymbox.sh
+++ b/git-applymbox.sh
@@ -21,6 +21,8 @@
USAGE='[-u] [-k] [-q] [-m] (-c .dotest/<num> | mbox) [signoff]'
. git-sh-setup
+git var GIT_COMMITTER_IDENT >/dev/null || exit
+
keep_subject= query_apply= continue= utf8= resume=t
while case "$#" in 0) break ;; esac
do
diff --git a/git-merge.sh b/git-merge.sh
index 74f0761..2b4a603 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -142,6 +142,8 @@ case "$#,$common,$no_commit" in
1,*,)
# We are not doing octopus, not fast forward, and have only
# one common. See if it is really trivial.
+ git var GIT_COMMITTER_IDENT >/dev/null || exit
+
echo "Trying really trivial in-index merge..."
git-update-index --refresh 2>/dev/null
if git-read-tree --trivial -m -u $common $head "$1" &&
@@ -179,6 +181,9 @@ case "$#,$common,$no_commit" in
;;
esac
+# We are going to make a new commit.
+git var GIT_COMMITTER_IDENT >/dev/null || exit
+
case "$use_strategies" in
'')
case "$#" in
diff --git a/git-resolve.sh b/git-resolve.sh
index 9263070..b53ede8 100755
--- a/git-resolve.sh
+++ b/git-resolve.sh
@@ -50,6 +50,9 @@ case "$common" in
;;
esac
+# We are going to make a new commit.
+git var GIT_COMMITTER_IDENT >/dev/null || exit
+
# Find an optimum merge base if there are more than one candidates.
LF='
'
--
1.2.1.g2902
^ permalink raw reply related
* [ANNOUNCE] GIT 1.2.2
From: Junio C Hamano @ 2006-02-19 8:56 UTC (permalink / raw)
To: git; +Cc: linux-kernel
The latest maintenance release GIT 1.2.2 is available at the
usual places:
http://www.kernel.org/pub/software/scm/git/
git-1.2.2.tar.{gz,bz2} (tarball)
RPMS/$arch/git-*-1.2.2-1.$arch.rpm (RPM)
Carl Worth fixed a longstanding annoyance of failed clone
leaving a half-built cloned directory. Contributions from
people new to the list are much appreciated. Long timers have
just leaned to live with these inconveniences, but I expect such
rough edges will be rounded out quickly as we gain more wider
user base.
The much talked about pack performance enhancement is not in
this release. In principle, 1.2.X series are supposed to be
bugfix only, so I can justifiably be lazy and keep things that
way, but we _could_ argue that the old pack-object had a
performance bug ;-).
We will decide what to do after it hits the master branch. I
think pack-object is important enough to be conservative about,
but at the same time its performance is veriy critical for the
public git server, so as it proves stable we probably would want
to have it on kernel.org.
----------------------------------------------------------------
Changes since v1.2.1 are as follows:
Carl Worth:
Trap exit to clean up created directory if clone fails.
Abstract test_create_repo out for use in tests.
Prevent git-upload-pack segfault if object cannot be found
Eric Wong:
archimport: remove files from the index before adding/updating
Jonas Fonseca:
git-rev-parse: Fix --short= option parsing
Document --short and --git-dir in git-rev-parse(1)
Martin Mares:
Fix retries in git-cvsimport
Shawn Pearce:
Make git-reset delete empty directories
^ permalink raw reply
* What's in git.git
From: Junio C Hamano @ 2006-02-19 8:56 UTC (permalink / raw)
To: git
* The 'master' branch has these since the last announcement.
Alexandre Julliard:
Add an Emacs interface in contrib.
Aneesh Kumar:
Add contrib/gitview from Aneesh.
Aneesh Kumar K.V:
Add a README for gitview
gitview: typofix
Carl Worth:
Trap exit to clean up created directory if clone fails.
Abstract test_create_repo out for use in tests.
Prevent git-upload-pack segfault if object cannot be found
Eric Wong:
Introducing contrib/git-svn.
git-svn: fix revision order when XML::Simple is not loaded
git-svn: ensure fetch always works chronologically.
git-svn: remove files from the index before adding/updating
archimport: remove files from the index before adding/updating
Fernando J. Pereda:
Allow building Git in systems without iconv
Jonas Fonseca:
git-rev-parse: Fix --short= option parsing
Document --short and --git-dir in git-rev-parse(1)
Junio C Hamano:
rebase: allow rebasing onto different base.
Detect misspelled pathspec to git-add
topo-order: make --date-order optional.
git-tag: -l to list tags (usability).
Add contrib/README.
SubmittingPatches: note on whitespaces
Martin Mares:
Fix retries in git-cvsimport
Shawn Pearce:
Make git-reset delete empty directories
* The 'next' branch, in addition, has these.
Johannes Schindelin:
Fix cpio call
Optionally support old diffs
Support Irix
Optionally work without python
Junio C Hamano:
pack-objects: reuse data from existing packs.
pack-objects: finishing touches.
git-repack: allow passing a couple of flags to pack-objects.
pack-objects: avoid delta chains that are too long.
Make "empty ident" error message a bit more helpful.
Delay "empty ident" errors until they really matter.
Keep Porcelainish from failing by broken ident after making changes.
fmt-merge-msg: say which branch things were merged into unless 'master'
Allow git-mv to accept ./ in paths.
Linus Torvalds:
Handling large files with GIT
Handling large files with GIT
git-merge-tree: generalize the "traverse <n> trees in sync" functionality
* The 'pu' branch, in addition, has these.
Johannes Schindelin:
Fixes for ancient versions of GNU make
Junio C Hamano:
read-tree: --prefix=<path>/ option.
write-tree: --prefix=<path>/ and --exclude=<prefix>/.
commit-tree: --bind <sha1> <path>/ option.
rev-list: simplify --object list generation.
rev-list: understand bound commits.
fsck-objects, convert-objects: understand bound commits.
^ permalink raw reply
* [PATCH] Add a Documentation/git-tools.txt
From: Marco Costalba @ 2006-02-19 10:00 UTC (permalink / raw)
To: git; +Cc: junkio
A brief survey of useful git tools, including third-party
and external projects.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
---
Please consider this more of a RFC then a finished patch.
Where possible, for each tool, the author's description is used as a summary.
I found http://git.or.cz/ a good source.
Tools are listed alphabetically in for each section.
Feel free to add/modify comments or tool's summaries. As stated this is still a
work in progress.
Documentation/git-tools.txt | 90 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 90 insertions(+), 0 deletions(-)
create mode 100644 Documentation/git-tools.txt
355a382ecca292363af2a0be4769c2b2fb2ea9e7
diff --git a/Documentation/git-tools.txt b/Documentation/git-tools.txt
new file mode 100644
index 0000000..7e563db
--- /dev/null
+++ b/Documentation/git-tools.txt
@@ -0,0 +1,90 @@
+A short git tools survey
+========================
+
+
+Introduction
+------------
+
+Apart from git contrib/ area there are some others third-party tools
+you may want to look.
+
+This document presents a brief summary of each tool and the corresponding link.
+
+
+Alternative/Argumentative Porcelains
+------------------------------------
+
+ - *Cogito* (http://www.kernel.org/pub/software/scm/cogito/)
+
+ Cogito is a version control system layered on top of the git tree history
+ storage system. It aims at seamless user interface and ease of
use, providing
+ generally smoother user experience than the "raw" Core GIT itself and indeed
+ many other version control systems.
+
+
+ - *pg* (http://www.spearce.org/category/projects/scm/pg/)
+
+ pg is a shell script wrapper around GIT to help the user manage a set of
+ patches to files. pg is somewhat like quilt or StGIT, but
it does have a
+ slightly different feature set.
+
+
+ - *StGit* (http://homepage.ntlworld.com/cmarinas/stgit/)
+
+ Stacked GIT provides a quilt-like patch management functionality in the GIT
+ environment. You can easily manage your patches in the
scope of GIT until they
+ get merged upstream.
+
+
+History Viewers
+---------------
+
+ - *gitk* (shipped with git-core)
+
+ gitk is a simple TK GUI for browsing history of GIT
repositories easily.
+
+
+ - *gitview* (contrib/)
+
+ gitview is a GTK based repository browser for git
+
+
+ - *gitweb* (ftp://ftp.kernel.org/pub/software/scm/gitweb/)
+
+ GITweb provides full-fledged web interface for GIT repositories.
+
+
+ - *qgit* (http://digilander.libero.it/mcostalba/)
+
+ QGit is a git/StGIT GUI viewer built on Qt/C++. QGit could be used
+ to browse history and directory tree, view annotated files, commit
+ changes cherry picking single files or applying patches.
+
+
+
+Foreign SCM interface
+---------------------
+
+ - *git-svn* (contrib/)
+
+ git-svn is a simple conduit for changesets between a
single Subversion
+ branch and git.
+
+
+ - *quilt2git / git2quilt* (http://home-tj.org/wiki/index.php/Misc)
+
+ These utilities convert patch series in a quilt
repository and commit
+ series in git back and forth.
+
+
+Others
+------
+
+ - *(h)gct* (http://www.cyd.liu.se/users/~freku045/gct/)
+
+ Commit Tool or (h)gct is a GUI enabled commit tool for git and
+ Mercurial (hg). It allows the user to view diffs, select
which files
+ to committed (or ignored / reverted) write commit
messages and perform
+ the commit itself.
+
+
--
1.2.0.g62a4
^ permalink raw reply related
* Re: [PATCH 2/2] Add 'stg uncommit' command
From: Catalin Marinas @ 2006-02-19 10:51 UTC (permalink / raw)
To: Karl Hasselström; +Cc: git
In-Reply-To: <20060217043128.14175.60168.stgit@backpacker.hemma.treskal.com>
Karl Hasselström wrote:
> Add an uncommit command, which is exactly the opposite of 'stg
> commit'.
Applied with two minor modifications. See below:
> --- a/stgit/commands/commit.py
> +++ b/stgit/commands/commit.py
> @@ -28,8 +28,9 @@ usage = """%prog [options]
> Merge the applied patches into the base of the current stack and
> remove them from the series while advancing the base.
>
> -Use this command only if you want to permanently store the applied
> -patches and no longer manage them with StGIT."""
> +Use this command if you want to permanently store the applied patches
> +and no longer manage them with StGIT. If you should change your mind
> +later, use 'stg uncommit'."""
I removed this change because, even if uncommit does the opposite of
commit does, the intended use is not to use commit/uncommit in pairs.
> diff --git a/stgit/commands/uncommit.py b/stgit/commands/uncommit.py
> new file mode 100644
> index 0000000..4ac0dfb
> --- /dev/null
> +++ b/stgit/commands/uncommit.py
> @@ -0,0 +1,80 @@
> +__copyright__ = """
> +Copyright (C) 2006, Catalin Marinas <catalin.marinas@gmail.com>
I added your name on the copyright since this is a new file.
Thanks,
Catalin
^ permalink raw reply
* Re: [PATCH] Add a Documentation/git-tools.txt
From: Junio C Hamano @ 2006-02-19 10:59 UTC (permalink / raw)
To: Marco Costalba; +Cc: git, junkio
In-Reply-To: <e5bfff550602190200j1ef3858as6a1564064dc81fef@mail.gmail.com>
"Marco Costalba" <mcostalba@gmail.com> writes:
> A brief survey of useful git tools, including third-party
> and external projects.
>
> Signed-off-by: Marco Costalba <mcostalba@gmail.com>
> ---
>
> Please consider this more of a RFC then a finished patch.
>
> Where possible, for each tool, the author's description is used as a summary.
> I found http://git.or.cz/ a good source.
Thanks for starting this.
Briefly mentioning tool's strength and weakness without being
too subjective would be very helpful to potential users. We
would encourage competition without making other tools sound
inferiour on subjective terms. So "this is similar to foobar
tool, but runs much faster, but has these limitations" would be
a good style, but "this draws much nicer picture than barboz"
without substantiating why it is nicer may be suboptimal. Also
I am a bit afraid that the summary can become stale unless
maintained actively. Hopefully the respective authors of tools
can keep us updated.
I am of two minds about mentioning things available from the git
repository, but I think it makes the survey more complete and
more useful in general to include them in the list. The private
draft I sent out to you earlier forgot to include the foreign
SCM interfaces.
^ permalink raw reply
* [PATCH] git-rev-list --help anywhere
From: Alex Riesen @ 2006-02-19 11:09 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Petr Baudis, git
Junio C Hamano, Sat, Feb 18, 2006 19:55:02 +0100:
> Petr Baudis <pasky@suse.cz> writes:
>
> > $ git-rev-list --help
> > fatal: Not a git repository
>
> Hmph, true. Ideas?
>
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
rev-list.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
0855207c43a83007e4c060a03c39269f379fed41
diff --git a/rev-list.c b/rev-list.c
index f2d1105..a059e45 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -755,10 +755,16 @@ static void handle_all(struct commit_lis
int main(int argc, const char **argv)
{
- const char *prefix = setup_git_directory();
+ const char *prefix;
struct commit_list *list = NULL;
int i, limited = 0;
+ for (i = 1 ; i < argc; i++)
+ if ( !strcmp(argv[i], "--help") )
+ usage(rev_list_usage);
+
+ prefix = setup_git_directory();
+
for (i = 1 ; i < argc; i++) {
int flags;
const char *arg = argv[i];
--
1.2.1.g59a08
^ permalink raw reply related
* Re: [PATCH] git-rev-list --help anywhere
From: linux @ 2006-02-19 11:26 UTC (permalink / raw)
To: raa.lkml; +Cc: git
>+ for (i = 1 ; i < argc; i++)
>+ if ( !strcmp(argv[i], "--help") )
>+ usage(rev_list_usage);
You might want to try something more like:
+ for (i = 1 ; i < argc; i++) {
+ if ( !strcmp(argv[i], "--help") )
+ usage(rev_list_usage);
+ if ( !strcmp(argv[i], "--") )
+ break;
+ }
So that you don't break in the perverse but legal case of
having a file named "--help".
^ permalink raw reply
* Re: gitk patch display corner-case bug
From: Paul Mackerras @ 2006-02-19 11:06 UTC (permalink / raw)
To: Karl Hasselström; +Cc: git
In-Reply-To: <20060218233618.GA29025@diana.vm.bytemark.co.uk>
Karl Hasselström writes:
> Totally correct except that it omitted the line consisting of only
> three dashes.
Could you check that the missing line is present in the output from
git-rev-list --header --parents --topo-order please?
Paul.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox