Git development
 help / color / mirror / Atom feed
* Re: CVS -> SVN -> Git
From: Simon 'corecode' Schubert @ 2007-07-19 19:15 UTC (permalink / raw)
  To: Julian Phillips; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0707131541140.11423@reaper.quantumfyre.co.uk>

Julian Phillips wrote:
> Has anyone managed to succssfully import a Subversion repository that 
> was initially imported from CVS using cvs2svn using fast-import?
> 
> It looks like cvs2svn has created a rather big mess.   It has created 
> single commits that change files in more than one branch and/or tag. It 
> also creates tags using more than one commit.  Now I come to try and 
> import the Subversion history into git and I'm having trouble creating a 
> sensible stream to feed into fast-import.

Did you try first converting the old CVS repo to git and then adding the svn changes?  That might give you much better results.

cheers
  simon

-- 
Serve - BSD     +++  RENT this banner advert  +++    ASCII Ribbon   /"\
Work - Mac      +++  space for low €€€ NOW!1  +++      Campaign     \ /
Party Enjoy Relax   |   http://dragonflybsd.org      Against  HTML   \
Dude 2c 2 the max   !   http://golden-apple.biz       Mail + News   / \

^ permalink raw reply

* Re: CVS -> SVN -> Git
From: Simon 'corecode' Schubert @ 2007-07-19 19:18 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Michael Haggerty, Julian Phillips, git
In-Reply-To: <46a038f90707132230n120e6392uaf5cd86ff10b6012@mail.gmail.com>

Martin Langhoff wrote:
> On 7/14/07, Michael Haggerty <mhagger@alum.mit.edu> wrote:
>> Incidentally, now that cvs2svn 2.0.0 is nearly out, I am thinking about
>> what it would take to write some other back ends for cvs2svn--turning
>> it, essentially, into cvs2xxx.  Most of the work that cvs2svn does is
>> inferring the most plausible history of the repository from CVS's
>> sketchy, incomplete, idiomatic, and often corrupt data.  This work
>> should also be useful for a cvs2git or cvs2hg or cvs2baz or ...
> 
> Great to hear that. I'm game if we can do something in this direction
> - surely we can make it talk to fastimport ;-)

In this context I suggest looking at fromcvs [1], my cvs->otherscm converter.  Right now it does git + hg (and sqlite for queries), but it probably is easily extensible for other targets.

> Does cvs2svn handle incremental imports, remembering any "guesses"
> taken earlier? Last time I looked at it, it had far better logic than
> cvsps, but it didn't do incremental imports, and repeated imports done
> at different times would "guess" different branching points for new
> branches, so it _really_ didn't support incrementals

fromcvs will also handle incremental imports.  If not, please tell me and I will try to fix it.

cheers
  simon

[1] http://ww2.fs.ei.tum.de/~corecode/hg/fromcvs/

-- 
Serve - BSD     +++  RENT this banner advert  +++    ASCII Ribbon   /"\
Work - Mac      +++  space for low €€€ NOW!1  +++      Campaign     \ /
Party Enjoy Relax   |   http://dragonflybsd.org      Against  HTML   \
Dude 2c 2 the max   !   http://golden-apple.biz       Mail + News   / \

^ permalink raw reply

* Re: [PATCH] Document how to tell git to not launch a pager
From: Thomas Glanzmann @ 2007-07-19 19:50 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Nikolai Weibull, David Kastrup, git
In-Reply-To: <alpine.LFD.0.999.0707191155100.27353@woody.linux-foundation.org>

Hello Linus,

I personally use screen a lot. I have a few screen sessions running:

	- a main screen carring 70 windows. Where I do my daily work and
	  read my mail on. I recompiled screen to support more than 40
	  winodws. This screen session runs on a well connected machine.
	  And consumes 175M resistent memory and 450M virtual memory.
	  That's mainly because I have 5000 lines of scrollback buffer
	  in each window and I had to recompile screen with all it's
	  buffers 2x to fight a symtom that it always crashed for me
	  when I resized it to fullscreen on a monitor with resolution
	  of 1600x1200. Yes I did fight symptoms some times even if I
	  don't like it. But had you ever a look at the screen source
	  code. It does make you puke.

	- a local screen. If I do something on a local machine I don't
	  open a single terminal I open a screen session with 5 windows.
	  Even if I only need a single shell.  The local screen only
	  stays open as long as I am logged in. I switch machines often.
	  I have a workstation at home, one at university, a laptop and
	  one at work.

	- a console screen (I do a lot of system administration) so the
	  serial consoles of the main servers at university are
	  connected to a screen session. Often are up to 5 people are
	  connected to that session. When you have to do some sort of
	  maintance work we often do a telephone conference while
	  everyone sees what is going on.

	- a so called development screen. As you can imagine having 70
	  windows open you do a lot of context switches and as you
	  stated before "do one thing and do it well" does not work that
	  way when there is you mailreader in the way on window 6, so
	  when I do something I have to focus on I use the development
	  screen. For short projects I use the development screen.

	- one screen for work related stuff.

> I actually like screen as a way to keep connections around. But the
> whole multiplexing is wrong, wrong, wrong. It violates the "do one
> thing, and do it well" thing. It makes screen do two things, and do
> them really badly as a result.

so true, as I stated above. When I notice that I go sideways I use one
screen per topic.

> And the "window manager" part is kind of a funny hack, but let's face
> it, you can do better by using separate windows.

Why I started to use screen is because I often switch workstations. And
I want to be able to go on where I left of. So I have the same
environment on every machine I have access to and synchronize this
environment. I use fvwm as window manager and have something configured
I call SmartStart. This is a fvwm function which focus an application if
it is already running and start it if it is not running.

	Ctrl Shift s => Main Screen
	Ctrl Shift l => Local Screen
	Ctrl Shift o => Opera
	...
	(thinkpad) [~] grep SmartStart .fvwm2rc | wc -l
	32


> And the multiplexor could have been done (and historically _has_ been
> done) better, by not limiting it to terminal sessions.

I actually have a macro for university that allows me to start X
application out of my screen session but most of the time I use local X
applications or use ssh forwarding if I have to get it from a remote
machine.

> But the *combination* of all three is just evil and stupid. And the
> choice of ctrl-A as the default command sequence (can you even
> override it? Don't know, don't care) is just insanity.

yes you can, but you get used to it.

>    networking, and you'd generally use ssh tunnelling for it and 
>    ssh-agent. But screen was never very good at it.

My main screen is running in its own ssh-agent session. So does my work
screen. My local has automatically the ssh-agent session from my
desktop session.

> IOW, I think screen sucks because it tries to do totally independent
> things, and then mixes them up in nasty ways, and for historical
> reasons uses a bad break character too.

Well, I have to aggreee with you. Sometimes I come back to a windows
where I stopped in the middle of doing something. And that is bad.
However screen makes me work faster and makes it possible to switch
locations often and pick up where you left of. It's biggest strength
it's it biggest weakness, too.

My screen configuration have dozens of people copied. I have this
fancy sticky status bar on the bottom.

http://wwwcip.informatik.uni-erlangen.de/~sithglan/shot.png

	Thomas

^ permalink raw reply

* [PATCH] Print an error when falling back to vi on a dumb terminal
From: Adam Roben @ 2007-07-19 21:10 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Johannes.Schindelin, Adam Roben
In-Reply-To: <Pine.LNX.4.64.0707191944560.14781@racer.site>

Signed-off-by: Adam Roben <aroben@apple.com>
---
On Jul 19, 2007, at 11:46 AM, Johannes Schindelin wrote:

> > -       commit_editor=$(git config core.editor || echo ${VISUAL:-$EDITOR})
> > -       case "$commit_editor,$TERM" in
> > +       case "$GIT_EDITOR,$TERM" in
> >         ,dumb)
> 
>         This can no longer happen, since ...
> 
> >         +set_editor() {
> >         +    GIT_EDITOR=$(git config core.editor || echo ${VISUAL:-${EDITOR:-vi}})
> >         +    export GIT_EDITOR
> >         +}
> 
>         ... "vi" is the last resort, not "", right?
> 
>         So I guess you just want to drag that test and warning into git-sh-setup 
>         (where I think it has a better home anyway).

Here you go. I'm not terribly happy with the error message, though. I tried to
be as clear as possible and to keep some of the nice information that was in
the git-commit error message. Please improve upon it if you can.

 git-am.sh                  |    4 ++--
 git-commit.sh              |   11 +----------
 git-rebase--interactive.sh |    2 +-
 git-sh-setup.sh            |   15 +++++++++++++--
 git-tag.sh                 |    2 +-
 5 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/git-am.sh b/git-am.sh
index a5de0a1..dd517f4 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -7,7 +7,6 @@ USAGE='[--signoff] [--dotest=<dir>] [--utf8 | --no-utf8] [--binary] [--3way]
   or, when resuming [--skip | --resolved]'
 . git-sh-setup
 set_reflog_action am
-set_editor
 require_work_tree
 
 git var GIT_COMMITTER_IDENT >/dev/null || exit
@@ -365,7 +364,8 @@ do
 		[yY]*) action=yes ;;
 		[aA]*) action=yes interactive= ;;
 		[nN]*) action=skip ;;
-		[eE]*) "$GIT_EDITOR" "$dotest/final-commit"
+		[eE]*) set_editor
+		       "$GIT_EDITOR" "$dotest/final-commit"
 		       action=again ;;
 		[vV]*) action=again
 		       LESS=-S ${PAGER:-less} "$dotest/patch" ;;
diff --git a/git-commit.sh b/git-commit.sh
index 9adb03c..4d5d898 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -6,7 +6,6 @@
 USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [[-i | -o] <path>...]'
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
-set_editor
 require_work_tree
 
 git rev-parse --verify HEAD >/dev/null 2>&1 || initial_commit=t
@@ -545,15 +544,7 @@ fi
 
 case "$no_edit" in
 '')
-	case "$GIT_EDITOR,$TERM" in
-	,dumb)
-		echo >&2 "Terminal is dumb but core.editor, VISUAL, and EDITOR"
-		echo >&2 "are undefined. Please supply the commit log message"
-		echo >&2 "using either -m or -F option.  A boilerplate log message"
-		echo >&2 "has been prepared in $GIT_DIR/COMMIT_EDITMSG"
-		exit 1
-		;;
-	esac
+	set_editor
 	git-var GIT_AUTHOR_IDENT > /dev/null  || die
 	git-var GIT_COMMITTER_IDENT > /dev/null  || die
 	$GIT_EDITOR "$GIT_DIR/COMMIT_EDITMSG"
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 32d1f53..27f8639 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -15,7 +15,6 @@ USAGE='(--continue | --abort | --skip | [--preserve-merges] [--verbose]
 
 . git-sh-setup
 require_work_tree
-set_editor
 
 DOTEST="$GIT_DIR/.dotest-merge"
 TODO="$DOTEST"/todo
@@ -415,6 +414,7 @@ EOF
 			die_abort "Nothing to do"
 
 		cp "$TODO" "$TODO".backup
+		set_editor
 		$GIT_EDITOR "$TODO" ||
 			die "Could not execute editor"
 
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index f43ab33..dbc4833 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -29,8 +29,19 @@ set_reflog_action() {
 }
 
 set_editor() {
-    GIT_EDITOR=$(git config core.editor || echo ${VISUAL:-${EDITOR:-vi}})
-    export GIT_EDITOR
+	GIT_EDITOR=$(git config core.editor || echo ${VISUAL:-${EDITOR}})
+	case "$GIT_EDITOR,$TERM" in
+	,dumb)
+		echo >&2 "No editor specified in core.editor, VISUAL, or EDITOR."
+		echo >&2 "Tried to fall back to vi but terminal is dumb."
+		echo >&2 "Please set one of these variables to an appropriate"
+		echo >&2 "editor or run $0 with options that will not cause an"
+		echo >&2 "editor to be invoked (e.g., -m or -F for git-commit)."
+		exit 1
+		;;
+	esac
+	GIT_EDITOR=${GIT_EDITOR:-vi}
+	export GIT_EDITOR
 }
 
 is_bare_repository () {
diff --git a/git-tag.sh b/git-tag.sh
index 0a6f2e7..f1a66d0 100755
--- a/git-tag.sh
+++ b/git-tag.sh
@@ -4,7 +4,6 @@
 USAGE='[-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg>] <tagname> [<head>]'
 SUBDIRECTORY_OK='Yes'
 . git-sh-setup
-set_editor
 
 message_given=
 annotate=
@@ -178,6 +177,7 @@ if [ "$annotate" ]; then
         ( echo "#"
           echo "# Write a tag message"
           echo "#" ) > "$GIT_DIR"/TAG_EDITMSG
+        set_editor
         $GIT_EDITOR "$GIT_DIR"/TAG_EDITMSG || exit
     else
         printf '%s\n' "$message" >"$GIT_DIR"/TAG_EDITMSG
-- 
1.5.3.rc2.21.gfc4a18-dirty

^ permalink raw reply related

* Re: [PATCH] Print an error when falling back to vi on a dumb terminal
From: Johannes Schindelin @ 2007-07-19 21:19 UTC (permalink / raw)
  To: Adam Roben; +Cc: git, Junio C Hamano
In-Reply-To: <11848794193942-git-send-email-aroben@apple.com>

Hi,

On Thu, 19 Jul 2007, Adam Roben wrote:

> Signed-off-by: Adam Roben <aroben@apple.com>

Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>

Thanks,
Dscho

^ permalink raw reply

* Re: git svn dcommit seg fault
From: Perrin Meyer @ 2007-07-19 22:16 UTC (permalink / raw)
  To: Eric Wong; +Cc: git
In-Reply-To: <20070718073450.GA30559@muzzle>


I did some more investigating on why git svn dcommit was seg faulting
for me, and I noticed that when I do my initial git svn clone 

$ git svn clone https://svn.eng.msli.com/perrin/trunk/TESTGIT/
TESTGIT_GIT/   

I always get an error
W: Ignoring error from SVN, path probably does not exist: (175007):
HTTP Path Not Found: REPORT request failed on
'/perrin/!svn/bc/100/trunk/TESTGIT':
'/perrin/!svn/bc/100/trunk/TESTGIT' path not found

This makes sense, since I did move my repo around a while back. Could
this be causing the seg fault problem I'm having with git svn
dcommit?

Just to be sure, I created a directory on our svn server's TEST2
repo, and I was able to use git svn to commit to it with git svn
dcommit just fine, so I think my git and svn setup is correct.

[perrin@whisper perrintest2_GIT]$ git svn dcommit
        M       testgit.c
Committed r130
        M       testgit.c
r130 = 01985d82b738b79bb479ef8817200ebe7c79eb94 (git-svn)
No changes between current HEAD and refs/remotes/git-svn
Resetting to the latest refs/remotes/git-svn

Thanks,

Perrin




--- Eric Wong <eric@petta-tech.com> wrote:

> Perrin Meyer <perrinmeyer@yahoo.com> wrote:
> > 
> > I'm able to clone svn repo's fine with
> > 
> > $ git svn clone https://svn.eng.msli.com/perrin/trunk/TESTGIT/ .
> > 
> > and I'm then able to use git commit to commit local changes, but 
> > when I try 
> > 
> > $ git svn dcommit
> > 
> > I get
> > 
> > [perrin@whisper TESTGIT]$ git svn dcommit
> >         M       test.c
> > Committed r717
> > Segmentation fault
> 
> 
> > As far as I can tell, the commit worked fine (verified by trying
> 'svn
> > update' on another box).
> > 
> > I've tried git version 1.5.2.3, 1.5.3-rc2, and the latest build,
> and
> > all give the seg fault.
> > 
> > I'm guessing it has something to do with using the https
> connection to
> > svn?
> 
> I primarily work with https repositories using git-svn and I
> haven't
> seen any segfaults in a while.  Which version of the SVN libraries
> do
> you have?  (git-svn --version will tell you).
> 
> -- 
> Eric Wong
> -
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* [PATCH] Honor the --sysconfdir option in configure.
From: Jan Merka @ 2007-07-19 22:16 UTC (permalink / raw)
  To: git

Fix the installation process so git uses the sysconfdir given to configure during installation instead of defaulting to $prefix/etc.
---
 config.mak.in |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/config.mak.in b/config.mak.in
index a3032e3..1c70571 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -11,6 +11,8 @@ TCLTK_PATH = @TCLTK_PATH@
 prefix = @prefix@
 exec_prefix = @exec_prefix@
 bindir = @bindir@
+sysconfdir = @sysconfdir@
+
 #gitexecdir = @libexecdir@/git-core/
 datarootdir = @datarootdir@
 template_dir = @datadir@/git-core/templates/
-- 
1.5.2.2

^ permalink raw reply related

* [PATCH] Make git tag a builtin.
From: Carlos Rica @ 2007-07-19 23:42 UTC (permalink / raw)
  To: git, Junio C Hamano, Johannes Schindelin

This replaces the script "git-tag.sh" with "builtin-tag.c".

The existing test suite for "git tag" guarantees the compatibility
with the features provided by the script version.

There are some minor changes in the behaviour of "git tag" here:
"git tag -v" now can get more than one tag to verify, like "git tag -d" does,
"git tag" with no arguments prints all tags, more like "git branch" does,
and "git tag -n" also prints all tags with annotations (without needing -l).
Tests and documentation were also updated to reflect these changes.

The program is currently calling the script "git verify-tag" for verify.
This can be changed porting it to C and calling its functions directly
from builtin-tag.c.

Signed-off-by: Carlos Rica <jasampler@gmail.com>
---

   This patch is a resend including the suggestions and corrections
   commented by Junio in the previous proposal for builtin-tag.c:
   http://article.gmane.org/gmane.comp.version-control.git/52246

   In this version, a bit of refactoring was also done grouping the common
   code between the previous functions delete_tags() and verify_tags().

   The function launch_editor will be moved to another file
   (editor.c is the suggested name), along with other tools
   for editing and reading text files, in order to share its code
   wiht other builtins like the upcoming builtin-commit.c from Kristian.

 Documentation/git-tag.txt                 |    8 +-
 Makefile                                  |    3 +-
 builtin-tag.c                             |  450 +++++++++++++++++++++++++++++
 builtin.h                                 |    1 +
 git-tag.sh => contrib/examples/git-tag.sh |    0
 git.c                                     |    1 +
 t/t7004-tag.sh                            |   88 +++++-
 7 files changed, 538 insertions(+), 13 deletions(-)
 create mode 100644 builtin-tag.c
 rename git-tag.sh => contrib/examples/git-tag.sh (100%)

diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index aee2c1b..119117f 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -12,7 +12,7 @@ SYNOPSIS
 'git-tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]  <name> [<head>]
 'git-tag' -d <name>...
 'git-tag' [-n [<num>]] -l [<pattern>]
-'git-tag' -v <name>
+'git-tag' -v <name>...

 DESCRIPTION
 -----------
@@ -23,7 +23,7 @@ Unless `-f` is given, the tag must not yet exist in

 If one of `-a`, `-s`, or `-u <key-id>` is passed, the command
 creates a 'tag' object, and requires the tag message.  Unless
-`-m <msg>` is given, an editor is started for the user to type
+`-m <msg>` or `-F <file>` is given, an editor is started for the user to type
 in the tag message.

 Otherwise just the SHA1 object name of the commit object is
@@ -59,15 +59,17 @@ OPTIONS
 	Delete existing tags with the given names.

 -v::
-	Verify the gpg signature of given the tag
+	Verify the gpg signature of the given tag names.

 -n <num>::
 	<num> specifies how many lines from the annotation, if any,
 	are printed when using -l.
 	The default is not to print any annotation lines.
+	If no number is given to `-n`, only the first line is printed.

 -l <pattern>::
 	List tags with names that match the given pattern (or all if no pattern is given).
+	Typing "git tag" without arguments, also lists all tags.

 -m <msg>::
 	Use the given tag message (instead of prompting)
diff --git a/Makefile b/Makefile
index 73b487f..8db6646 100644
--- a/Makefile
+++ b/Makefile
@@ -206,7 +206,7 @@ SCRIPT_SH = \
 	git-pull.sh git-rebase.sh git-rebase--interactive.sh \
 	git-repack.sh git-request-pull.sh git-reset.sh \
 	git-sh-setup.sh \
-	git-tag.sh git-verify-tag.sh \
+	git-verify-tag.sh \
 	git-am.sh \
 	git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
 	git-merge-resolve.sh git-merge-ours.sh \
@@ -361,6 +361,7 @@ BUILTIN_OBJS = \
 	builtin-show-branch.o \
 	builtin-stripspace.o \
 	builtin-symbolic-ref.o \
+	builtin-tag.o \
 	builtin-tar-tree.o \
 	builtin-unpack-objects.o \
 	builtin-update-index.o \
diff --git a/builtin-tag.c b/builtin-tag.c
new file mode 100644
index 0000000..507f510
--- /dev/null
+++ b/builtin-tag.c
@@ -0,0 +1,450 @@
+/*
+ * Builtin "git tag"
+ *
+ * Copyright (c) 2007 Kristian HÞgsberg <krh@redhat.com>,
+ *                    Carlos Rica <jasampler@gmail.com>
+ * Based on git-tag.sh and mktag.c by Linus Torvalds.
+ */
+
+#include "cache.h"
+#include "builtin.h"
+#include "refs.h"
+#include "tag.h"
+#include "run-command.h"
+
+static const char builtin_tag_usage[] =
+  "git-tag [-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg> | -F <file>] <tagname> [<head>]";
+
+static char signingkey[1000];
+
+static void launch_editor(const char *path, char **buffer, unsigned long *len)
+{
+	const char *editor, *terminal;
+	struct child_process child;
+	const char *args[3];
+	int fd;
+
+	editor = getenv("VISUAL");
+	if (!editor)
+		editor = getenv("EDITOR");
+
+	terminal = getenv("TERM");
+	if (!editor && (!terminal || !strcmp(terminal, "dumb"))) {
+		fprintf(stderr,
+		"Terminal is dumb but no VISUAL nor EDITOR defined.\n"
+		"Please supply the message using either -m or -F option.\n");
+		exit(1);
+	}
+
+	if (!editor)
+		editor = "vi";
+
+	memset(&child, 0, sizeof(child));
+	child.argv = args;
+	args[0] = editor;
+	args[1] = path;
+	args[2] = NULL;
+
+	if (run_command(&child))
+		die("There was a problem with the editor %s.", editor);
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		die("could not open '%s': %s", path, strerror(errno));
+	if (read_fd(fd, buffer, len)) {
+		free(*buffer);
+		die("could not read message file '%s': %s",
+						path, strerror(errno));
+	}
+	close(fd);
+}
+
+struct tag_filter {
+	const char *pattern;
+	int lines;
+};
+
+#define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----"
+
+static int show_reference(const char *refname, const unsigned char *sha1,
+			  int flag, void *cb_data)
+{
+	struct tag_filter *filter = cb_data;
+
+	if (!fnmatch(filter->pattern, refname, 0)) {
+		int i;
+		unsigned long size;
+		enum object_type type;
+		char *buf, *sp, *eol;
+		size_t len;
+
+		if (!filter->lines) {
+			printf("%s\n", refname);
+			return 0;
+		}
+		printf("%-15s ", refname);
+
+		sp = buf = read_sha1_file(sha1, &type, &size);
+		if (!buf || !size)
+			return 0;
+		/* skip header */
+		while (sp + 1 < buf + size &&
+				!(sp[0] == '\n' && sp[1] == '\n'))
+			sp++;
+		/* only take up to "lines" lines, and strip the signature */
+		for (i = 0, sp += 2; i < filter->lines && sp < buf + size &&
+				prefixcmp(sp, PGP_SIGNATURE "\n");
+				i++) {
+			if (i)
+				printf("\n    ");
+			eol = memchr(sp, '\n', size - (sp - buf));
+			len = eol ? eol - sp : size - (sp - buf);
+			fwrite(sp, len, 1, stdout);
+			if (!eol)
+				break;
+			sp = eol + 1;
+		}
+		putchar('\n');
+		free(buf);
+	}
+
+	return 0;
+}
+
+static int list_tags(const char *pattern, int lines)
+{
+	struct tag_filter filter;
+	char *newpattern;
+
+	if (pattern == NULL)
+		pattern = "";
+
+	/* prepend/append * to the shell pattern: */
+	newpattern = xmalloc(strlen(pattern) + 3);
+	sprintf(newpattern, "*%s*", pattern);
+
+	filter.pattern = newpattern;
+	filter.lines = lines;
+
+	for_each_tag_ref(show_reference, (void *) &filter);
+
+	free(newpattern);
+
+	return 0;
+}
+
+typedef int (*func_tag)(const char *name, const char *ref,
+				const unsigned char *sha1);
+
+static int do_tag_names(const char **argv, func_tag fn)
+{
+	const char **p;
+	char ref[PATH_MAX];
+	int had_error = 0;
+	unsigned char sha1[20];
+
+	for (p = argv; *p; p++) {
+		if (snprintf(ref, sizeof(ref), "refs/tags/%s", *p)
+					>= sizeof(ref)) {
+			error("tag name too long: %.*s...", 50, *p);
+			had_error = 1;
+			continue;
+		}
+		if (!resolve_ref(ref, sha1, 1, NULL)) {
+			error("tag '%s' not found.", *p);
+			had_error = 1;
+			continue;
+		}
+		if (fn(*p, ref, sha1))
+			had_error = 1;
+	}
+	return had_error;
+}
+
+static int delete_tag(const char *name, const char *ref,
+				const unsigned char *sha1)
+{
+	if (delete_ref(ref, sha1))
+		return 1;
+	printf("Deleted tag '%s'\n", name);
+	return 0;
+}
+
+static int verify_tag(const char *name, const char *ref,
+				const unsigned char *sha1)
+{
+	const char *argv_verify_tag[] = {"git-verify-tag",
+					"-v", "SHA1_HEX", NULL};
+	argv_verify_tag[2] = sha1_to_hex(sha1);
+
+	if (run_command_v_opt(argv_verify_tag, 0))
+		return error("could not verify the tag '%s'", name);
+	return 0;
+}
+
+static ssize_t do_sign(char *buffer, size_t size, size_t max)
+{
+	struct child_process gpg;
+	const char *args[4];
+	char *bracket;
+	int len;
+
+	if (!*signingkey) {
+		if (strlcpy(signingkey, git_committer_info(1),
+				sizeof(signingkey)) >= sizeof(signingkey))
+			return error("committer info too long.");
+		bracket = strchr(signingkey, '>');
+		if (bracket)
+			bracket[1] = '\0';
+	}
+
+	memset(&gpg, 0, sizeof(gpg));
+	gpg.argv = args;
+	gpg.in = -1;
+	gpg.out = -1;
+	args[0] = "gpg";
+	args[1] = "-bsau";
+	args[2] = signingkey;
+	args[3] = NULL;
+
+	if (start_command(&gpg))
+		return error("could not run gpg.");
+
+	write_or_die(gpg.in, buffer, size);
+	close(gpg.in);
+	gpg.close_in = 0;
+	len = read_in_full(gpg.out, buffer + size, max - size);
+
+	finish_command(&gpg);
+
+	if (len == max - size)
+		return error("could not read the entire signature from gpg.");
+
+	return size + len;
+}
+
+static const char tag_template[] =
+	"\n"
+	"#\n"
+	"# Write a tag message\n"
+	"#\n";
+
+static int git_tag_config(const char *var, const char *value)
+{
+	if (!strcmp(var, "user.signingkey")) {
+		if (!value)
+			die("user.signingkey without value");
+		if (strlcpy(signingkey, value, sizeof(signingkey))
+						>= sizeof(signingkey))
+			die("user.signingkey value too long");
+		return 0;
+	}
+
+	return git_default_config(var, value);
+}
+
+#define MAX_SIGNATURE_LENGTH 1024
+/* message must be NULL or allocated, it will be reallocated and freed */
+static void create_tag(const unsigned char *object, const char *tag,
+		       char *message, int sign, unsigned char *result)
+{
+	enum object_type type;
+	char header_buf[1024], *buffer;
+	int header_len, max_size;
+	unsigned long size;
+
+	type = sha1_object_info(object, NULL);
+	if (type <= 0)
+	    die("bad object type.");
+
+	header_len = snprintf(header_buf, sizeof(header_buf),
+			  "object %s\n"
+			  "type %s\n"
+			  "tag %s\n"
+			  "tagger %s\n\n",
+			  sha1_to_hex(object),
+			  typename(type),
+			  tag,
+			  git_committer_info(1));
+
+	if (header_len >= sizeof(header_buf))
+		die("tag header too big.");
+
+	if (!message) {
+		char *path;
+		int fd;
+
+		/* write the template message before editing: */
+		path = xstrdup(git_path("TAG_EDITMSG"));
+		fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
+		if (fd < 0)
+			die("could not create file '%s': %s",
+						path, strerror(errno));
+		write_or_die(fd, tag_template, strlen(tag_template));
+		close(fd);
+
+		launch_editor(path, &buffer, &size);
+
+		unlink(path);
+		free(path);
+	}
+	else {
+		buffer = message;
+		size = strlen(message);
+	}
+
+	size = stripspace(buffer, size, 1);
+
+	if (!message && !size)
+		die("no tag message?");
+
+	/* insert the header and add the '\n' if needed: */
+	max_size = header_len + size + (sign ? MAX_SIGNATURE_LENGTH : 0) + 1;
+	buffer = xrealloc(buffer, max_size);
+	if (size)
+		buffer[size++] = '\n';
+	memmove(buffer + header_len, buffer, size);
+	memcpy(buffer, header_buf, header_len);
+	size += header_len;
+
+	if (sign) {
+		size = do_sign(buffer, size, max_size);
+		if (size < 0)
+			die("unable to sign the tag");
+	}
+
+	if (write_sha1_file(buffer, size, tag_type, result) < 0)
+		die("unable to write tag file");
+	free(buffer);
+}
+
+int cmd_tag(int argc, const char **argv, const char *prefix)
+{
+	unsigned char object[20], prev[20];
+	int annotate = 0, sign = 0, force = 0, lines = 0;
+	char *message = NULL;
+	char ref[PATH_MAX];
+	const char *object_ref, *tag;
+	int i;
+	struct ref_lock *lock;
+
+	git_config(git_tag_config);
+
+	for (i = 1; i < argc; i++) {
+		const char *arg = argv[i];
+
+		if (arg[0] != '-')
+			break;
+		if (!strcmp(arg, "-a")) {
+			annotate = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-s")) {
+			annotate = 1;
+			sign = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-f")) {
+			force = 1;
+			continue;
+		}
+		if (!strcmp(arg, "-n")) {
+			if (i + 1 == argc || *argv[i + 1] == '-')
+				/* no argument */
+				lines = 1;
+			else
+				lines = isdigit(*argv[++i]) ?
+					atoi(argv[i]) : 1;
+			continue;
+		}
+		if (!strcmp(arg, "-m")) {
+			annotate = 1;
+			i++;
+			if (i == argc)
+				die("option -m needs an argument.");
+			message = xstrdup(argv[i]);
+			continue;
+		}
+		if (!strcmp(arg, "-F")) {
+			unsigned long len;
+			int fd;
+
+			annotate = 1;
+			i++;
+			if (i == argc)
+				die("option -F needs an argument.");
+
+			if (!strcmp(argv[i], "-"))
+				fd = 0;
+			else {
+				fd = open(argv[i], O_RDONLY);
+				if (fd < 0)
+					die("could not open '%s': %s",
+						argv[i], strerror(errno));
+			}
+			len = 1024;
+			message = xmalloc(len);
+			if (read_fd(fd, &message, &len)) {
+				free(message);
+				die("cannot read %s", argv[i]);
+			}
+			continue;
+		}
+		if (!strcmp(arg, "-u")) {
+			annotate = 1;
+			sign = 1;
+			i++;
+			if (i == argc)
+				die("option -u needs an argument.");
+			if (strlcpy(signingkey, argv[i], sizeof(signingkey))
+							>= sizeof(signingkey))
+				die("argument to option -u too long");
+			continue;
+		}
+		if (!strcmp(arg, "-l")) {
+			return list_tags(argv[i + 1], lines);
+		}
+		if (!strcmp(arg, "-d")) {
+			return do_tag_names(argv + i + 1, delete_tag);
+		}
+		if (!strcmp(arg, "-v")) {
+			return do_tag_names(argv + i + 1, verify_tag);
+		}
+		usage(builtin_tag_usage);
+	}
+
+	if (i == argc) {
+		if (annotate)
+			usage(builtin_tag_usage);
+		return list_tags(NULL, lines);
+	}
+	tag = argv[i++];
+
+	object_ref = i < argc ? argv[i] : "HEAD";
+	if (i + 1 < argc)
+		die("too many params");
+
+	if (get_sha1(object_ref, object))
+		die("Failed to resolve '%s' as a valid ref.", object_ref);
+
+	if (snprintf(ref, sizeof(ref), "refs/tags/%s", tag) >= sizeof(ref))
+		die("tag name too long: %.*s...", 50, tag);
+	if (check_ref_format(ref))
+		die("'%s' is not a valid tag name.", tag);
+
+	if (!resolve_ref(ref, prev, 1, NULL))
+		hashclr(prev);
+	else if (!force)
+		die("tag '%s' already exists", tag);
+
+	if (annotate)
+		create_tag(object, tag, message, sign, object);
+
+	lock = lock_any_ref_for_update(ref, prev, 0);
+	if (!lock)
+		die("%s: cannot lock the ref", ref);
+	if (write_ref_sha1(lock, object, NULL) < 0)
+		die("%s: cannot update the ref", ref);
+
+	return 0;
+}
diff --git a/builtin.h b/builtin.h
index 4cc228d..ac7417f 100644
--- a/builtin.h
+++ b/builtin.h
@@ -70,6 +70,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);
 extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
 extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
 extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
+extern int cmd_tag(int argc, const char **argv, const char *prefix);
 extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_unpack_objects(int argc, const char **argv, const char *prefix);
 extern int cmd_update_index(int argc, const char **argv, const char *prefix);
diff --git a/git-tag.sh b/contrib/examples/git-tag.sh
similarity index 100%
rename from git-tag.sh
rename to contrib/examples/git-tag.sh
diff --git a/git.c b/git.c
index a647f9c..eb9e5ca 100644
--- a/git.c
+++ b/git.c
@@ -363,6 +363,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "show", cmd_show, RUN_SETUP | USE_PAGER },
 		{ "stripspace", cmd_stripspace },
 		{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
+		{ "tag", cmd_tag, RUN_SETUP },
 		{ "tar-tree", cmd_tar_tree },
 		{ "unpack-objects", cmd_unpack_objects, RUN_SETUP },
 		{ "update-index", cmd_update_index, RUN_SETUP },
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 17de2a9..a0be164 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -5,7 +5,7 @@

 test_description='git-tag

-Basic tests for operations with tags.'
+Tests for operations with tags.'

 . ./test-lib.sh

@@ -16,11 +16,15 @@ tag_exists () {
 }

 # todo: git tag -l now returns always zero, when fixed, change this test
-test_expect_success 'listing all tags in an empty tree should succeed' \
-	'git tag -l'
+test_expect_success 'listing all tags in an empty tree should succeed' '
+	git tag -l &&
+	git tag
+'

-test_expect_success 'listing all tags in an empty tree should output nothing' \
-	'test `git-tag -l | wc -l` -eq 0'
+test_expect_success 'listing all tags in an empty tree should output nothing' '
+	test `git-tag -l | wc -l` -eq 0 &&
+	test `git-tag | wc -l` -eq 0
+'

 test_expect_failure 'looking for a tag in an empty tree should fail' \
 	'tag_exists mytag'
@@ -49,11 +53,15 @@ test_expect_success 'creating a tag using default HEAD should succeed' '
 	git tag mytag
 '

-test_expect_success 'listing all tags if one exists should succeed' \
-	'git-tag -l'
+test_expect_success 'listing all tags if one exists should succeed' '
+	git-tag -l &&
+	git-tag
+'

-test_expect_success 'listing all tags if one exists should output that tag' \
-	'test `git-tag -l` = mytag'
+test_expect_success 'listing all tags if one exists should output that tag' '
+	test `git-tag -l` = mytag &&
+	test `git-tag` = mytag
+'

 # pattern matching:

@@ -165,6 +173,8 @@ test_expect_success 'listing all tags should print them ordered' '
 	git tag v1.0 &&
 	git tag t210 &&
 	git tag -l > actual &&
+	git diff expect actual &&
+	git tag > actual &&
 	git diff expect actual
 '

@@ -264,6 +274,10 @@ test_expect_failure \
 	'trying to verify a non-annotated and non-signed tag should fail' \
 	'git-tag -v non-annotated-tag'

+test_expect_failure \
+	'trying to verify many non-annotated or unknown tags, should fail' \
+	'git-tag -v unknown-tag1 non-annotated-tag unknown-tag2'
+
 # creating annotated tags:

 get_tag_msg () {
@@ -306,6 +320,18 @@ test_expect_success \
 	git diff expect actual
 '

+cat >inputmsg <<EOF
+A message from the
+standard input
+EOF
+get_tag_header stdin-annotated-tag $commit commit $time >expect
+cat inputmsg >>expect
+test_expect_success 'creating an annotated tag with -F - should succeed' '
+	git-tag -F - stdin-annotated-tag <inputmsg &&
+	get_tag_msg stdin-annotated-tag >actual &&
+	git diff expect actual
+'
+
 # blank and empty messages:

 get_tag_header empty-annotated-tag $commit commit $time >expect
@@ -551,6 +577,12 @@ test_expect_success \
 	! git-tag -v file-annotated-tag
 '

+test_expect_success \
+	'trying to verify two annotated non-signed tags should fail' '
+	tag_exists annotated-tag file-annotated-tag &&
+	! git-tag -v annotated-tag file-annotated-tag
+'
+
 # creating and verifying signed tags:

 gpg --version >/dev/null
@@ -589,9 +621,47 @@ test_expect_success 'creating a signed tag with -m message should succeed' '
 	git diff expect actual
 '

+cat >sigmsgfile <<EOF
+Another signed tag
+message in a file.
+EOF
+get_tag_header file-signed-tag $commit commit $time >expect
+cat sigmsgfile >>expect
+echo '-----BEGIN PGP SIGNATURE-----' >>expect
+test_expect_success \
+	'creating a signed tag with -F messagefile should succeed' '
+	git-tag -s -F sigmsgfile file-signed-tag &&
+	get_tag_msg file-signed-tag >actual &&
+	git diff expect actual
+'
+
+cat >siginputmsg <<EOF
+A signed tag message from
+the standard input
+EOF
+get_tag_header stdin-signed-tag $commit commit $time >expect
+cat siginputmsg >>expect
+echo '-----BEGIN PGP SIGNATURE-----' >>expect
+test_expect_success 'creating a signed tag with -F - should succeed' '
+	git-tag -s -F - stdin-signed-tag <siginputmsg &&
+	get_tag_msg stdin-signed-tag >actual &&
+	git diff expect actual
+'
+
 test_expect_success 'verifying a signed tag should succeed' \
 	'git-tag -v signed-tag'

+test_expect_success 'verifying two signed tags in one command should succeed' \
+	'git-tag -v signed-tag file-signed-tag'
+
+test_expect_success \
+	'verifying many signed and non-signed tags should fail' '
+	! git-tag -v signed-tag annotated-tag &&
+	! git-tag -v file-annotated-tag file-signed-tag &&
+	! git-tag -v annotated-tag file-signed-tag file-annotated-tag &&
+	! git-tag -v signed-tag annotated-tag file-signed-tag
+'
+
 test_expect_success 'verifying a forged tag should fail' '
 	forged=$(git cat-file tag signed-tag |
 		sed -e "s/signed-tag/forged-tag/" |
-- 
1.5.0

^ permalink raw reply related

* Re: [RFC PATCH] Re: Empty directories...
From: Junio C Hamano @ 2007-07-20  0:01 UTC (permalink / raw)
  To: Brian Gernhardt
  Cc: David Kastrup, Shawn O.Pearce, Linus Torvalds, Matthieu Moy,
	Johannes Schindelin, Git Mailing List
In-Reply-To: <FA38709A-7C68-4D66-BA26-B5ED49DFA85A@silverinsanity.com>

Brian Gernhardt <benji@silverinsanity.com> writes:

> My apologies for the wasted bandwidth arguing for things that had
> already been decided.

Sorry, who decided what?

^ permalink raw reply

* [PATCH] gitweb cleanup: Move @diff_opts declaration earlier
From: Jakub Narebski @ 2007-07-20  0:15 UTC (permalink / raw)
  To: git; +Cc: Jakub Narebski

Move @diff_opts declaration earlier, so that all gitweb options are
together (and not separated by %feature hash and some subroutines),
with the exception of $GITWEB_CONFIG which must be after all option
variables including %feature hash.

While at it, in the moved comment, note that diff option '-C' implies
'-M', instead of suggesting that '-M', '-C' is required.

Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
 gitweb/gitweb.perl |   20 ++++++++++----------
 1 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index c8ba3a2..6754e26 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -104,6 +104,16 @@ our $mimetypes_file = undef;
 # could be even 'utf-8' for the old behavior)
 our $fallback_encoding = 'latin1';
 
+# rename detection options for git-diff and git-diff-tree
+# - default is '-M', with the cost proportional to
+#   (number of removed files) * (number of new files).
+# - more costly is '-C' (which implies '-M'), with the cost proportional to
+#   (number of changed files + number of removed files) * (number of new files)
+# - even more costly is '-C', '--find-copies-harder' with cost
+#   (number of files in the original tree) * (number of new files)
+# - one might want to include '-B' option, e.g. '-B', '-M'
+our @diff_opts = ('-M'); # taken from git_commit
+
 # You define site-wide feature defaults here; override them with
 # $GITWEB_CONFIG as necessary.
 our %feature = (
@@ -310,16 +320,6 @@ sub check_export_ok {
 		(!$export_ok || -e "$dir/$export_ok"));
 }
 
-# rename detection options for git-diff and git-diff-tree
-# - default is '-M', with the cost proportional to
-#   (number of removed files) * (number of new files).
-# - more costly is '-C' (or '-C', '-M'), with the cost proportional to
-#   (number of changed files + number of removed files) * (number of new files)
-# - even more costly is '-C', '--find-copies-harder' with cost
-#   (number of files in the original tree) * (number of new files)
-# - one might want to include '-B' option, e.g. '-B', '-M'
-our @diff_opts = ('-M'); # taken from git_commit
-
 our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
 do $GITWEB_CONFIG if -e $GITWEB_CONFIG;
 
-- 
1.5.2.4

^ permalink raw reply related

* Re: [PATCH] Print an error when falling back to vi on a dumb terminal
From: Junio C Hamano @ 2007-07-20  0:15 UTC (permalink / raw)
  To: Adam Roben; +Cc: git, Johannes.Schindelin
In-Reply-To: <11848794193942-git-send-email-aroben@apple.com>

Adam Roben <aroben@apple.com> writes:

> Here you go. I'm not terribly happy with the error message, though. I tried to
> be as clear as possible and to keep some of the nice information that was in
> the git-commit error message. Please improve upon it if you can.
>
>  git-am.sh                  |    4 ++--
>  git-commit.sh              |   11 +----------
>  git-rebase--interactive.sh |    2 +-
>  git-sh-setup.sh            |   15 +++++++++++++--
>  git-tag.sh                 |    2 +-
>  5 files changed, 18 insertions(+), 16 deletions(-)
>
> diff --git a/git-am.sh b/git-am.sh
> index a5de0a1..dd517f4 100755
> --- a/git-am.sh
> +++ b/git-am.sh
> @@ -7,7 +7,6 @@ USAGE='[--signoff] [--dotest=<dir>] [--utf8 | --no-utf8] [--binary] [--3way]
>    or, when resuming [--skip | --resolved]'
>  . git-sh-setup
>  set_reflog_action am
> -set_editor
>  require_work_tree
>  
>  git var GIT_COMMITTER_IDENT >/dev/null || exit
> @@ -365,7 +364,8 @@ do
>  		[yY]*) action=yes ;;
>  		[aA]*) action=yes interactive= ;;
>  		[nN]*) action=skip ;;
> -		[eE]*) "$GIT_EDITOR" "$dotest/final-commit"
> +		[eE]*) set_editor
> +		       "$GIT_EDITOR" "$dotest/final-commit"
>  		       action=again ;;
>  		[vV]*) action=again
>  		       LESS=-S ${PAGER:-less} "$dotest/patch" ;;

Sounds sane.

Could you please re-diff to make this into a single patch
without intermediate "Oh, doing it this way is cleaner", and
also with Dscho's Ack?  I do not think we would need to have 3
commits for this topic --- it is not like wide userbase tested
each iteration.

^ permalink raw reply

* Re: [RFC PATCH] Re: Empty directories...
From: Linus Torvalds @ 2007-07-20  0:15 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Brian Gernhardt, David Kastrup, Shawn O.Pearce, Matthieu Moy,
	Johannes Schindelin, Git Mailing List
In-Reply-To: <7vk5sw2ba7.fsf@assigned-by-dhcp.cox.net>



On Thu, 19 Jul 2007, Junio C Hamano wrote:
>
> Brian Gernhardt <benji@silverinsanity.com> writes:
> 
> > My apologies for the wasted bandwidth arguing for things that had
> > already been decided.
> 
> Sorry, who decided what?

I think people who didn't know how the world works decided that 
directories that were added manually as directories would stay as 
directories even after the last file was removed.

That's physically impossible with the git data-structures (since there is 
no way of saving "this directory was added empty" in the tree structures, 
nor any point to it), so I think it's just insane rambling.

I dunno. I think empty directories are worth supporting, mainly to be able 
to capture other SCM's notion of what _they_ track, but quite frankly, the 
level of discussion about them hasn't been exactly inspiring. It seems to 
be more about "this is what we'd like to see, without really having a 
reason for it, nor necessarily understanding what we're talking about" 
than "this is realistic and useful and here are patches".

I *do* think that it's a very valid argument that if you import something 
from SVN that has an empty directory, the git import should show that.  

That's about the only valid argument I've ever seen for them, though, and 
I think that's totally irrelevant to such issues as to whether "git rm 
file/in/directory" should remove the directory(*) from being tracked by 
git when the file goes away or not.

			Linus
 
(*) And, for anybody confused about the issue, the answer to the latter 
question is an emphatic: "Yes it should, live with it, and if you want the 
directory back, you had better add it back as an empty directory"

^ permalink raw reply

* Re: [REVISED PATCH 2/6] Introduce commit notes
From: Junio C Hamano @ 2007-07-20  0:20 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Johannes Schindelin, Alberto Bertogli, git, Johan Herland
In-Reply-To: <alpine.LFD.0.999.0707191032320.27353@woody.linux-foundation.org>

Linus Torvalds <torvalds@linux-foundation.org> writes:

> On Thu, 19 Jul 2007, Junio C Hamano wrote:
>> > ...
>> > But the real problem of this approach of course is that this is
>> > not reliable and can get a false match.  You can find your
>> > beginning NUL in the SHA-1 part of one entry, and terminating
>> > NUL later in the SHA-1 part of next entry, and you will never
>> > notice.
>
> [ I didn't react to this in your first email, because I thought you were 
>   talking about your "use the rules for the ASCII part", and thought you 
>   talked about how *that* was not reliable and can get a false match). But 
>   it seems that you were actually talking about the NUL character test ]
>
> Nope, wrong.
>
> Why? Because there must always be a NUL *between* different SHA1's. 
> There's *always* a NUL character that precedes a SHA1. So when you have 
> two NUL characters (with no other NUL's between them), you *know* that 
> they cannot be from two different SHA1's. If the first one was from an 
> earlier SHA1, then the second one is *guaranteed* to be the one that 
> happens *before* the next SHA1.
>
> See?

Ok.  As usual, you are more right than I am ;-).

^ permalink raw reply

* Re: [PATCH (REVISED)] Add core.editor configuration variable
From: Junio C Hamano @ 2007-07-20  0:20 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Brian Gernhardt, Andy Parkins, git, Adam Roben
In-Reply-To: <alpine.LFD.0.999.0707191531330.22541@xanadu.home>

Nicolas Pitre <nico@cam.org> writes:

> On Thu, 19 Jul 2007, Brian Gernhardt wrote:
>
>> For many people commit is more "core" to their git usage than write-tree and
>> commit-tree.  At this point, it's less an extra layer porcelain and more the
>> standard interface.  It's a result of the wonderful attempts to make git more
>> user friendly.
>> 
>> As far as [core] being only for plumbing, I disagree with that premise as
>> well.  Any option that is used across many of the git commands is a core
>> (meaning central) option.
>
> That pov certainly makes sense to me.

Good to see the discussion converged while I was trapped in the
day job.  So core.editor it is?
 

^ permalink raw reply

* [PATCH] Add core.editor configuration variable
From: Adam Roben @ 2007-07-20  0:28 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Adam Roben
In-Reply-To: <7vfy3k2an7.fsf@assigned-by-dhcp.cox.net>

This variable lets you specify an editor that will be launched in preference to
the EDITOR and VISUAL environment variables.

Signed-off-by: Adam Roben <aroben@apple.com>
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
On Jul 19, 2007, at 5:15 PM, Junio C Hamano wrote:

> Could you please re-diff to make this into a single patch
> without intermediate "Oh, doing it this way is cleaner", and
> also with Dscho's Ack?  I do not think we would need to have 3
> commits for this topic --- it is not like wide userbase tested
> each iteration.

 Documentation/git-commit.txt     |    9 +++++----
 Documentation/git-send-email.txt |    4 ++--
 git-am.sh                        |    3 ++-
 git-commit.sh                    |   12 ++----------
 git-rebase--interactive.sh       |    3 ++-
 git-send-email.perl              |    3 +--
 git-sh-setup.sh                  |   16 ++++++++++++++++
 git-tag.sh                       |    3 ++-
 8 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index f96142f..5caad56 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -244,10 +244,11 @@ on the Subject: line and the rest of the commit in the body.
 
 include::i18n.txt[]
 
-ENVIRONMENT VARIABLES
----------------------
-The command specified by either the VISUAL or EDITOR environment
-variables is used to edit the commit log message.
+ENVIRONMENT AND CONFIGURATION VARIABLES
+---------------------------------------
+The editor used to edit the commit log message will be chosen from the
+core.editor configuration variable, the VISUAL environment variable, or the
+EDITOR environment variable (in that order).
 
 HOOKS
 -----
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 293686c..e7723c9 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -44,8 +44,8 @@ The --cc option must be repeated for each user you want on the cc list.
 	value; if that is unspecified, default to --chain-reply-to.
 
 --compose::
-	Use $EDITOR to edit an introductory message for the
-	patch series.
+	Use core.editor, $VISUAL, or $EDITOR to edit an introductory message
+	for the patch series.
 
 --from::
 	Specify the sender of the emails.  This will default to
diff --git a/git-am.sh b/git-am.sh
index e5e6f2c..dd517f4 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -364,7 +364,8 @@ do
 		[yY]*) action=yes ;;
 		[aA]*) action=yes interactive= ;;
 		[nN]*) action=skip ;;
-		[eE]*) "${VISUAL:-${EDITOR:-vi}}" "$dotest/final-commit"
+		[eE]*) set_editor
+		       "$GIT_EDITOR" "$dotest/final-commit"
 		       action=again ;;
 		[vV]*) action=again
 		       LESS=-S ${PAGER:-less} "$dotest/patch" ;;
diff --git a/git-commit.sh b/git-commit.sh
index 3f3de17..4d5d898 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -544,18 +544,10 @@ fi
 
 case "$no_edit" in
 '')
-	case "${VISUAL:-$EDITOR},$TERM" in
-	,dumb)
-		echo >&2 "Terminal is dumb but no VISUAL nor EDITOR defined."
-		echo >&2 "Please supply the commit log message using either"
-		echo >&2 "-m or -F option.  A boilerplate log message has"
-		echo >&2 "been prepared in $GIT_DIR/COMMIT_EDITMSG"
-		exit 1
-		;;
-	esac
+	set_editor
 	git-var GIT_AUTHOR_IDENT > /dev/null  || die
 	git-var GIT_COMMITTER_IDENT > /dev/null  || die
-	${VISUAL:-${EDITOR:-vi}} "$GIT_DIR/COMMIT_EDITMSG"
+	$GIT_EDITOR "$GIT_DIR/COMMIT_EDITMSG"
 	;;
 esac
 
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index f395076..27f8639 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -414,7 +414,8 @@ EOF
 			die_abort "Nothing to do"
 
 		cp "$TODO" "$TODO".backup
-		${VISUAL:-${EDITOR:-vi}} "$TODO" ||
+		set_editor
+		$GIT_EDITOR "$TODO" ||
 			die "Could not execute editor"
 
 		test -z "$(grep -ve '^$' -e '^#' < $TODO)" &&
diff --git a/git-send-email.perl b/git-send-email.perl
index 7552cac..ad17b4e 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -341,8 +341,7 @@ GIT: for the patch you are writing.
 EOT
 	close(C);
 
-	my $editor = $ENV{EDITOR};
-	$editor = 'vi' unless defined $editor;
+	my $editor = $repo->config("core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
 	system($editor, $compose_filename);
 
 	open(C2,">",$compose_filename . ".final")
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 4ed07e9..dbc4833 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -28,6 +28,22 @@ set_reflog_action() {
 	fi
 }
 
+set_editor() {
+	GIT_EDITOR=$(git config core.editor || echo ${VISUAL:-${EDITOR}})
+	case "$GIT_EDITOR,$TERM" in
+	,dumb)
+		echo >&2 "No editor specified in core.editor, VISUAL, or EDITOR."
+		echo >&2 "Tried to fall back to vi but terminal is dumb."
+		echo >&2 "Please set one of these variables to an appropriate"
+		echo >&2 "editor or run $0 with options that will not cause an"
+		echo >&2 "editor to be invoked (e.g., -m or -F for git-commit)."
+		exit 1
+		;;
+	esac
+	GIT_EDITOR=${GIT_EDITOR:-vi}
+	export GIT_EDITOR
+}
+
 is_bare_repository () {
 	git rev-parse --is-bare-repository
 }
diff --git a/git-tag.sh b/git-tag.sh
index 1c25d88..f1a66d0 100755
--- a/git-tag.sh
+++ b/git-tag.sh
@@ -177,7 +177,8 @@ if [ "$annotate" ]; then
         ( echo "#"
           echo "# Write a tag message"
           echo "#" ) > "$GIT_DIR"/TAG_EDITMSG
-        ${VISUAL:-${EDITOR:-vi}} "$GIT_DIR"/TAG_EDITMSG || exit
+        set_editor
+        $GIT_EDITOR "$GIT_DIR"/TAG_EDITMSG || exit
     else
         printf '%s\n' "$message" >"$GIT_DIR"/TAG_EDITMSG
     fi
-- 
1.5.3.rc2.21.gfc4a18-dirty

^ permalink raw reply related

* Re: [RFC PATCH] Re: Empty directories...
From: Linus Torvalds @ 2007-07-20  0:33 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Brian Gernhardt, David Kastrup, Shawn O.Pearce, Matthieu Moy,
	Johannes Schindelin, Git Mailing List
In-Reply-To: <alpine.LFD.0.999.0707191706120.27249@woody.linux-foundation.org>



On Thu, 19 Jul 2007, Linus Torvalds wrote:
> 
> That's physically impossible with the git data-structures (since there is 
> no way of saving "this directory was added empty" in the tree structures, 
> nor any point to it), so I think it's just insane rambling.

Of course, it's physically *possible* to have a tree that contains two 
entries for the same name: first the "empty tree" and then the "real 
tree", and yeah, in theory you could track things that way.

So I guess the "physically impossible" was a bit strong. You'd have to 
have a totally insane format, and you'd have to violate deeply seated 
rules about what trees look like (and the index too, for that matter: we'd 
have to do the same for the index, and keep the S_IFDIR entry alive 
despite having other entries that are children of it), but it's 
*possible*.

It's just a really bad idea.

So to be sane, when you add files, the empty directory entry has to go 
away. Otherwise you could have two very different trees that encode the 
same *content* (just with different ways of getting there - depending on 
whether you have a history with empty trees or not), and that's very much 
against the philosophy of git, and breaks some fundamental rules (like the 
fact that "same content == same SHA1").

In fact, that may be the best way to explain why it's *not* an option to 
have "empty trees remain empty trees if we remove the last file from 
them": git fundamnetally tracks "content snapshots", and anything that 
implies the content containing any history is against the rules.

So the whole notion of "remembering" whether a directory was added 
explicitly as an empty directory or not is just not a sensible concept in 
git. 

		Linus

^ permalink raw reply

* Re: [PATCH] Install man3 manpages to $PREFIX/share/man/man3 even for site installs
From: Junio C Hamano @ 2007-07-20  0:42 UTC (permalink / raw)
  To: Randal L. Schwartz; +Cc: git, martin f. krafft
In-Reply-To: <11848491502417-git-send-email-madduck@madduck.net>

Randal, I cannot decide if this is the right thing to do, or 
better than what we currently do.  Could you care to enlighten
us please?

"martin f. krafft" <madduck@madduck.net> writes:

> MakeMaker supports three installation modes: perl, site, and vendor. The first
> and third install manpages to $PREFIX/share/man, only site installs to
> $PREFIX/man. For consistency with the rest of git, which does not make the
> distinction and writes all manpages to $PREFIX/share/man, this change makes
> sure that perl does too, even when it's installed in site mode.
>
> Signed-off-by: martin f. krafft <madduck@madduck.net>
> ---
>  perl/Makefile.PL |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/perl/Makefile.PL b/perl/Makefile.PL
> index 4375161..6aecd89 100644
> --- a/perl/Makefile.PL
> +++ b/perl/Makefile.PL
> @@ -29,5 +29,6 @@ WriteMakefile(
>  	VERSION_FROM    => 'Git.pm',
>  	PM		=> \%pm,
>  	MAKEFILE	=> 'perl.mak',
> +	INSTALLSITEMAN3DIR => '$(SITEPREFIX)/share/man/man3',
>  	%extra
>  );
> -- 
> 1.5.3.rc2.19.gc4fba-dirty

^ permalink raw reply

* Re: [PATCH] Install man3 manpages to $PREFIX/share/man/man3 even  for site installs
From: Randal L. Schwartz @ 2007-07-20  0:46 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, martin f. krafft
In-Reply-To: <7vzm1r29df.fsf@assigned-by-dhcp.cox.net>

>>>>> "Junio" == Junio C Hamano <gitster@pobox.com> writes:

Junio> Randal, I cannot decide if this is the right thing to do, or 
Junio> better than what we currently do.  Could you care to enlighten
Junio> us please?

I'll have to research it.  On *every single* major release of Perl, and even
some of the minor ones, the rules for what Makefile.PL does have changed.
It's really maddening.

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

^ permalink raw reply

* Re: [RFC PATCH] Re: Empty directories...
From: Junio C Hamano @ 2007-07-20  2:24 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Brian Gernhardt, David Kastrup, Shawn O.Pearce, Matthieu Moy,
	Johannes Schindelin, Git Mailing List
In-Reply-To: <alpine.LFD.0.999.0707191726510.27249@woody.linux-foundation.org>

Linus Torvalds <torvalds@linux-foundation.org> writes:

> So the whole notion of "remembering" whether a directory was added 
> explicitly as an empty directory or not is just not a sensible concept in 
> git. 

That is true if it is implemented as David suggested, to have a
phony "." entry in the tree object itself.  The object name of
such a tree (when it contains blobs and trees underneath) will
be different from a tree that contains the same set of blobs and
trees.  It would destroy the fundamental concepts of git.

But you _could_ treat that "should-be-kept-even-when-empty"-ness
just like we treat executable bit on blobs, I think.

When blobs with the same contents but of different type (REG vs
LNK) and regular file with or without executable bit are entered
in git, they all get the same SHA-1 but we can still tell them
apart because the index and the tree entry have mode bits.  So
hypothetically, you could introduce "sticky" directory in tree
entries to mark "this will not go away when emptied".

In a 'tree' object, they might appear as:

        40000 ordinary-directory '\0' 20-byte SHA-1
        41000 directory-dontremove-even-if-empty '\0' 20-byte SHA-1

In 'index', as your "I'm soft" patch, we do not have to add
nonsticky kind of tree nodes, but for "empty" ones, we can add:

	041000 directory-dontremove-even-if-empty '\0' 20-byte SHA-1

in the index and (unlike your patch) keep it there even after a
blob or a tree is added underneath it.

The "sticky" bit on such a directory would have to obey the
usual rule of 3-way merge, which would be a huge change to do
so, but I do no see there is anything fundamental that prevents
you from doing this.  Other than the fact that probably no git
long timer is interested in spending time on such a feature,
that is.

Obviously, this "sticky" bit will cascade up and make your
otherwise equivalent parent tree's different, but I think that
is just as a sane behaviour as two trees that contain the same
blob with only executable-bit differences have different names.

This will involve a lot of changes, so I would not recommend
anybody doing so, though.

^ permalink raw reply

* Re: [RFC PATCH] Re: Empty directories...
From: Linus Torvalds @ 2007-07-20  2:31 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Brian Gernhardt, David Kastrup, Shawn O.Pearce, Matthieu Moy,
	Johannes Schindelin, Git Mailing List
In-Reply-To: <7vir8f24o2.fsf@assigned-by-dhcp.cox.net>



On Thu, 19 Jul 2007, Junio C Hamano wrote:
> 
> But you _could_ treat that "should-be-kept-even-when-empty"-ness
> just like we treat executable bit on blobs, I think.

True. Or you could make it a path attribute and/or a per-repository 
decision, so that while the data wouldn't necessarily be in the database 
itself, the user could specify the behaviour he wanted.

> This will involve a lot of changes, so I would not recommend
> anybody doing so, though.

Agreed. The upside just isn't there.

		Linus

^ permalink raw reply

* Re: [PATCH] gitweb: snapshot cleanups & support for offering multiple formats
From: Junio C Hamano @ 2007-07-20  4:29 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: Matt McCutchen, git, Petr Baudis, Luben Tuikov
In-Reply-To: <200707191105.19735.jnareb@gmail.com>

Jakub Narebski <jnareb@gmail.com> writes:

> On Thu, 19 July 2007, Junio C Hamano wrote:
> ...
>> I really hate to having to say something like that in the
>> RelNotes.  I do not think this is a good enough reason to break
>> existing configurations; I would not want to be defending that
>> change.
>
> Would it be sufficient to put above alert/warning in commit message,
> RelNotes and gitweb/INSTALL (or gitweb/README), and add rule to Makefile
> to convert old configuration, or at least check if GITWEB_CONFIG uses
> old snapshot configuration? This way if somebody is installing/upgrading
> gitweb by hand he/she would know what needs possibly to be changes, and
> if somebody uses "make gitweb/gitweb.cgi" he would get big fat warning,
> and info how to convert gitweb config.
>
> By the way, I think it was a mistake to use different syntax in the
> %feature hash ([content-encoding, suffix, program]) than in repo config
> override (name).

That's true.  I'd rather see this polished a bit more before
applying.

^ permalink raw reply

* Re: [PATCH] Internationalization of git-gui
From: Shawn O. Pearce @ 2007-07-20  4:55 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Christian Stimming, git
In-Reply-To: <Pine.LNX.4.64.0707191323510.14781@racer.site>

Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> On Thu, 19 Jul 2007, Christian Stimming wrote:
> 
> > Does this implementation look okay?
> 
> This is valuable work, but unfortunately, it does not follow the 
> recommendation in Documentation/SubmittingPatches at all.
> 
> For starters, please send the patches inlined, one per mail.  And you 
> might want to Cc the maintainer of git-gui (Shawn Pearce), too...

I agree that internationalization of git-gui is worth doing.
I've thought about working on it, but haven't yet because nobody
else has seemed interested in having it done.  Apparently someone
is, so patches towards that end are most welcome.

-- 
Shawn.

^ permalink raw reply

* Re: [REVISED PATCH 2/6] Introduce commit notes
From: Shawn O. Pearce @ 2007-07-20  4:59 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Linus Torvalds, Johannes Schindelin, Alberto Bertogli, git,
	Johan Herland
In-Reply-To: <7vodi83fg7.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <gitster@pobox.com> wrote:
> I've long time ago concluded that if we care about reliability
> (and we do very much), a bisectable tree without breaking
> backward compatibility is impossible.  I was hoping to find a
> "hole" in tree object format so that I can place an extended
> section that is invisible to older versions of git, and place a
> table that records offsets of each tree entries to help
> bisection and/or perhaps a hash table to help look-up, but I do
> not think it is possible.
...
> But the tree object format
> is designed so tight that I do not see there is any place to put
> an extension section.

I came to the same conclusion the last time I thought about this
problem, for all the same reasons you outlined.  And came up with
pack v4.  Because the only way I could see that we could produce
a more optimal tree was to just use a different *compression* of
the tree, while still keeping its data the same.  Nico seemed to
agree at the time, because he worked on the prototype with me.  :-)

Its still hanging around in my fastimport repository.  But has not
been merged with any recent Git, and it still needs a lot of work.

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH] Internationalization of git-gui
From: Shawn O. Pearce @ 2007-07-20  5:04 UTC (permalink / raw)
  To: Brett Schwarz; +Cc: Christian Stimming, git, Paul Mackerras
In-Reply-To: <622391.43998.qm@web38909.mail.mud.yahoo.com>

Brett Schwarz <brett_schwarz@yahoo.com> wrote:
> This is a good idea. However, I assume the _ proc is just sugar. It
> might be better to follow a more "standard" way for this, and just
> import the msgcat namespace, and then you can just use [mc]. For
> example:
> 
> package require msgcat
> namespace import ::msgcat::*
>   .
>   .
>   .
> .mbar add cascade -label [mc Repository] -menu .mbar.repository

Not just better, I'd prefer it.  The proc name "_" is cute but
is just too darn short.  I would much prefer to use "mc" and just
say that "mc" in all of git-gui's namespaces is reserved for the
message catalog, much as "cb" is already reserved for setting up
callbacks for Tcl/Tk event handlers.

-- 
Shawn.

^ permalink raw reply

* [PATCH] Add GIT_EDITOR environment variable and core.editor configuration variable
From: Adam Roben @ 2007-07-20  5:09 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Adam Roben
In-Reply-To: <11848913032579-git-send-email-aroben@apple.com>

These variables let you specify an editor that will be launched in preference to
the EDITOR and VISUAL environment variables. The order of preference is
GIT_EDITOR, core.editor, EDITOR, VISUAL.

Signed-off-by: Adam Roben <aroben@apple.com>
---
This patch obsoletes all the previous ones I've sent for this change.

After discussing a bit with Junio and Shawn, this patch introduces
git-sh-setup::git_editor() to handle invoking the editor. It also respects the
GIT_EDITOR environment variable for overriding the choice of editor.

Hopefully this is the last version of this patch :-)

 Documentation/git-commit.txt     |   10 ++++++----
 Documentation/git-send-email.txt |    4 ++--
 git-am.sh                        |    2 +-
 git-commit.sh                    |   11 +----------
 git-rebase--interactive.sh       |    2 +-
 git-send-email.perl              |    7 +++----
 git-sh-setup.sh                  |   15 +++++++++++++++
 git-tag.sh                       |    2 +-
 8 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index f96142f..8e0e7e2 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -244,10 +244,12 @@ on the Subject: line and the rest of the commit in the body.
 
 include::i18n.txt[]
 
-ENVIRONMENT VARIABLES
----------------------
-The command specified by either the VISUAL or EDITOR environment
-variables is used to edit the commit log message.
+ENVIRONMENT AND CONFIGURATION VARIABLES
+---------------------------------------
+The editor used to edit the commit log message will be chosen from the
+GIT_EDITOR environment variable, the core.editor configuration variable, the
+VISUAL environment variable, or the EDITOR environment variable (in that
+order).
 
 HOOKS
 -----
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 293686c..d243ed1 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -44,8 +44,8 @@ The --cc option must be repeated for each user you want on the cc list.
 	value; if that is unspecified, default to --chain-reply-to.
 
 --compose::
-	Use $EDITOR to edit an introductory message for the
-	patch series.
+	Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an
+	introductory message for the patch series.
 
 --from::
 	Specify the sender of the emails.  This will default to
diff --git a/git-am.sh b/git-am.sh
index e5e6f2c..bfd65dc 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -364,7 +364,7 @@ do
 		[yY]*) action=yes ;;
 		[aA]*) action=yes interactive= ;;
 		[nN]*) action=skip ;;
-		[eE]*) "${VISUAL:-${EDITOR:-vi}}" "$dotest/final-commit"
+		[eE]*) git_editor "$dotest/final-commit"
 		       action=again ;;
 		[vV]*) action=again
 		       LESS=-S ${PAGER:-less} "$dotest/patch" ;;
diff --git a/git-commit.sh b/git-commit.sh
index 3f3de17..92749df 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -544,18 +544,9 @@ fi
 
 case "$no_edit" in
 '')
-	case "${VISUAL:-$EDITOR},$TERM" in
-	,dumb)
-		echo >&2 "Terminal is dumb but no VISUAL nor EDITOR defined."
-		echo >&2 "Please supply the commit log message using either"
-		echo >&2 "-m or -F option.  A boilerplate log message has"
-		echo >&2 "been prepared in $GIT_DIR/COMMIT_EDITMSG"
-		exit 1
-		;;
-	esac
 	git-var GIT_AUTHOR_IDENT > /dev/null  || die
 	git-var GIT_COMMITTER_IDENT > /dev/null  || die
-	${VISUAL:-${EDITOR:-vi}} "$GIT_DIR/COMMIT_EDITMSG"
+	git_editor "$GIT_DIR/COMMIT_EDITMSG"
 	;;
 esac
 
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index f395076..a2d4d09 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -414,7 +414,7 @@ EOF
 			die_abort "Nothing to do"
 
 		cp "$TODO" "$TODO".backup
-		${VISUAL:-${EDITOR:-vi}} "$TODO" ||
+		git_editor "$TODO" ||
 			die "Could not execute editor"
 
 		test -z "$(grep -ve '^$' -e '^#' < $TODO)" &&
diff --git a/git-send-email.perl b/git-send-email.perl
index 7552cac..a09b1c9 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -49,8 +49,8 @@ Options:
    --bcc          Specify a list of email addresses that should be Bcc:
 		  on all the emails.
 
-   --compose      Use \$EDITOR to edit an introductory message for the
-                  patch series.
+   --compose      Use \$GIT_EDITOR, core.editor, \$EDITOR, or \$VISUAL to edit
+		  an introductory message for the patch series.
 
    --subject      Specify the initial "Subject:" line.
                   Only necessary if --compose is also set.  If --compose
@@ -341,8 +341,7 @@ GIT: for the patch you are writing.
 EOT
 	close(C);
 
-	my $editor = $ENV{EDITOR};
-	$editor = 'vi' unless defined $editor;
+	my $editor = $ENV{GIT_EDITOR} || $repo->config("core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
 	system($editor, $compose_filename);
 
 	open(C2,">",$compose_filename . ".final")
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 4ed07e9..c51985e 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -28,6 +28,21 @@ set_reflog_action() {
 	fi
 }
 
+git_editor() {
+	GIT_EDITOR=${GIT_EDITOR:-$(git config core.editor || echo ${VISUAL:-${EDITOR}})}
+	case "$GIT_EDITOR,$TERM" in
+	,dumb)
+		echo >&2 "No editor specified in GIT_EDITOR, core.editor, VISUAL,"
+		echo >&2 "or EDITOR. Tried to fall back to vi but terminal is dumb."
+		echo >&2 "Please set one of these variables to an appropriate"
+		echo >&2 "editor or run $0 with options that will not cause an"
+		echo >&2 "editor to be invoked (e.g., -m or -F for git-commit)."
+		exit 1
+		;;
+	esac
+	"${GIT_EDITOR:-vi}" "$1"
+}
+
 is_bare_repository () {
 	git rev-parse --is-bare-repository
 }
diff --git a/git-tag.sh b/git-tag.sh
index 1c25d88..5ee3f50 100755
--- a/git-tag.sh
+++ b/git-tag.sh
@@ -177,7 +177,7 @@ if [ "$annotate" ]; then
         ( echo "#"
           echo "# Write a tag message"
           echo "#" ) > "$GIT_DIR"/TAG_EDITMSG
-        ${VISUAL:-${EDITOR:-vi}} "$GIT_DIR"/TAG_EDITMSG || exit
+        git_editor "$GIT_DIR"/TAG_EDITMSG || exit
     else
         printf '%s\n' "$message" >"$GIT_DIR"/TAG_EDITMSG
     fi
-- 
1.5.3.rc2.20.g2e098-dirty

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox