Git development
 help / color / mirror / Atom feed
* Re: [PATCH] Add git-shell.
From: Linus Torvalds @ 2005-10-24  0:55 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0510231751040.10477@g5.osdl.org>



On Sun, 23 Oct 2005, Linus Torvalds wrote:
> 
> Did you actually test that it works as somebody's login-shell and can be 
> used for pushing?
> 
> I think it should add "pull" functionality too

Gaah, I only read your description, didn't look closer at the patch. The 
description just said "push", but you added the pull side too, and 
apparently even tested it. Goodie.

Never mind me.

			Linus

^ permalink raw reply

* Re: [PATCH] Add git-shell.
From: Linus Torvalds @ 2005-10-24  0:52 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vhdb7vk64.fsf_-_@assigned-by-dhcp.cox.net>



On Sun, 23 Oct 2005, Junio C Hamano wrote:
>
> This adds a very git specific restricted shell, that can be
> added to /etc/shells and set to the pw_shell in the /etc/passwd
> file, to give users ability to push into repositories over ssh
> without giving them full interactive shell acount.

Did you actually test that it works as somebody's login-shell and can be 
used for pushing?

I think it should add "pull" functionality too, so that you can have 
restricted reading (hey, git may be open source, but not everything that 
is maintained in it necessarily will be..)

			Linus

^ permalink raw reply

* [PATCH] Add git-shell.
From: Junio C Hamano @ 2005-10-24  0:21 UTC (permalink / raw)
  To: git; +Cc: Linus Torvalds
In-Reply-To: <Pine.LNX.4.64.0510231427230.10477@g5.osdl.org>

This adds a very git specific restricted shell, that can be
added to /etc/shells and set to the pw_shell in the /etc/passwd
file, to give users ability to push into repositories over ssh
without giving them full interactive shell acount.

[jc: I updated Linus' patch to match what the current sq_quote()
 does.]

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

   This one has the '!' dequoting I mentioned earlier, and
   actually has been tested twice.

   The system administrator should set things up so that the
   system default PATH environment variable lets users run the
   supported commands.

   We currently rely on the user to have a full shell access for
   repository administrative actions (e.g. git-init-db to create
   a repository, git-repack, and hooks management).  Probably
   some of them may need to become accessible from git-shell,
   but I do not know which ones offhand:

   - Creating a repository.  Probably wherever the user has
     write privilege, or maybe only under the home directory --
     the policy would be up to the system administrator, with
     usual filesystem quota applied.

   - I think setting up hooks should be forbidden -- the user
     can execute arbitrary commands if we allowed it.  Instead,
     the administrator can set things up for people, and would
     probably make creative use of hooks/update to implement
     access control (e.g. forbidding non-fast-forward pushes).

   - Similarly, packing can be left to hooks/post-update or cron
     job, either of which is under administrator control.

 Makefile |    2 +-
 quote.c  |   41 ++++++++++++++++++++++++++++++++++++++++-
 quote.h  |    6 ++++++
 shell.c  |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 106 insertions(+), 2 deletions(-)
 create mode 100644 shell.c

applies-to: c043f0993afe5c057409ef748ce313c89c20c7dc
f176536e2cd5949fa134d8b24dc07dd1f0744b6f
diff --git a/Makefile b/Makefile
index 5bdf3cc..5b0306d 100644
--- a/Makefile
+++ b/Makefile
@@ -116,7 +116,7 @@ PROGRAMS = \
 	git-merge-index$X git-mktag$X git-pack-objects$X git-patch-id$X \
 	git-peek-remote$X git-prune-packed$X git-read-tree$X \
 	git-receive-pack$X git-rev-list$X git-rev-parse$X \
-	git-send-pack$X git-show-branch$X \
+	git-send-pack$X git-show-branch$X git-shell$X \
 	git-show-index$X git-ssh-fetch$X \
 	git-ssh-upload$X git-tar-tree$X git-unpack-file$X \
 	git-unpack-objects$X git-update-index$X git-update-server-info$X \
diff --git a/quote.c b/quote.c
index 009e694..e662a7d 100644
--- a/quote.c
+++ b/quote.c
@@ -15,6 +15,11 @@
 #undef EMIT
 #define EMIT(x) ( (++len < n) && (*bp++ = (x)) )
 
+static inline int need_bs_quote(char c)
+{
+	return (c == '\'' || c == '!');
+}
+
 size_t sq_quote_buf(char *dst, size_t n, const char *src)
 {
 	char c;
@@ -23,7 +28,7 @@ size_t sq_quote_buf(char *dst, size_t n,
 
 	EMIT('\'');
 	while ((c = *src++)) {
-		if (c == '\'' || c == '!') {
+		if (need_bs_quote(c)) {
 			EMIT('\'');
 			EMIT('\\');
 			EMIT(c);
@@ -52,6 +57,40 @@ char *sq_quote(const char *src)
 	return buf;
 }
 
+char *sq_dequote(char *arg)
+{
+	char *dst = arg;
+	char *src = arg;
+	char c;
+
+	if (*src != '\'')
+		return NULL;
+	for (;;) {
+		c = *++src;
+		if (!c)
+			return NULL;
+		if (c != '\'') {
+			*dst++ = c;
+			continue;
+		}
+		/* We stepped out of sq */
+		switch (*++src) {
+		case '\0':
+			*dst = 0;
+			return arg;
+		case '\\':
+			c = *++src;
+			if (need_bs_quote(c) && *++src == '\'') {
+				*dst++ = c;
+				continue;
+			}
+		/* Fallthrough */
+		default:
+			return NULL;
+		}
+	}
+}
+
 /*
  * C-style name quoting.
  *
diff --git a/quote.h b/quote.h
index 2fdde3b..2486e6e 100644
--- a/quote.h
+++ b/quote.h
@@ -31,6 +31,12 @@
 extern char *sq_quote(const char *src);
 extern size_t sq_quote_buf(char *dst, size_t n, const char *src);
 
+/* This unwraps what sq_quote() produces in place, but returns
+ * NULL if the input does not look like what sq_quote would have
+ * produced.
+ */
+extern char *sq_dequote(char *);
+
 extern int quote_c_style(const char *name, char *outbuf, FILE *outfp,
 			 int nodq);
 extern char *unquote_c_style(const char *quoted, const char **endp);
diff --git a/shell.c b/shell.c
new file mode 100644
index 0000000..2c4789e
--- /dev/null
+++ b/shell.c
@@ -0,0 +1,59 @@
+#include "cache.h"
+#include "quote.h"
+
+static int do_generic_cmd(const char *me, char *arg)
+{
+	const char *my_argv[4];
+
+	arg = sq_dequote(arg);
+	if (!arg)
+		die("bad argument");
+
+	my_argv[0] = me;
+	my_argv[1] = arg;
+	my_argv[2] = NULL;
+
+	return execvp(me, (char**) my_argv);
+}
+
+static struct commands {
+	const char *name;
+	int (*exec)(const char *me, char *arg);
+} cmd_list[] = {
+	{ "git-receive-pack", do_generic_cmd },
+	{ "git-upload-pack", do_generic_cmd },
+	{ NULL },
+};
+
+int main(int argc, char **argv)
+{
+	char *prog;
+	struct commands *cmd;
+
+	/* We want to see "-c cmd args", and nothing else */
+	if (argc != 3 || strcmp(argv[1], "-c"))
+		die("What do you think I am? A shell?");
+
+	prog = argv[2];
+	argv += 2;
+	argc -= 2;
+	for (cmd = cmd_list ; cmd->name ; cmd++) {
+		int len = strlen(cmd->name);
+		char *arg;
+		if (strncmp(cmd->name, prog, len))
+			continue;
+		arg = NULL;
+		switch (prog[len]) {
+		case '\0':
+			arg = NULL;
+			break;
+		case ' ':
+			arg = prog + len + 1;
+			break;
+		default:
+			continue;
+		}
+		exit(cmd->exec(cmd->name, arg));
+	}
+	die("unrecognized command '%s'", prog);
+}
---
0.99.8.GIT

^ permalink raw reply related

* Re: User-relative paths
From: Junio C Hamano @ 2005-10-23 23:02 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andreas Ericsson, git
In-Reply-To: <Pine.LNX.4.64.0510231427230.10477@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> It's incomplete and almost certainly buggy and generally broken, but 
> here's somethign that you _could_ install as "git-shell", and then put 
> that as somebodys shell in /etc/passwd, and it's a start. A very rough 
> start.
>
> Somebody else gets to test it out ;)
>
> +		if (c != '\'') {
> +			*dst++ = c;
> +			continue;
> +		}
> +		switch (*++src) {
> +		case '\0':
> +			*dst = 0;
> +			return arg;
> +		case '\\':
> +			if (*++src == '\'' &&
> +			    *++src == '\'') {
> +				*dst = '\'';
> +				continue;
> +			}
> +		/* Fallthrough */
> +		default:

I think this misses HPA's addition to minimally suppport csh
braindamage (bang bang).

^ permalink raw reply

* Re: User-relative paths
From: Junio C Hamano @ 2005-10-23 22:57 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andreas Ericsson, git
In-Reply-To: <Pine.LNX.4.64.0510231427230.10477@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

>> But it is orthogonal to what you are doing in this patch.
>
> Well, not necessarily.
>
> It's quite arguable that sanity testing might be per-user and could be 
> done by the shell. I'm not at all sure that srvside_chdir() should do any 
> extra testing: if you have real ssh access, the user has the right to do 
> anything he damn well pleases.

The point of the patch, unless I am mistaken, is to add ~user/
expansion to the pathname grokking, so that a remote user does
not have to know exactly where on the server each user's home
directory is.

I agree 100% with you that srvside_chdir() is not the place to
do policy checking.  In order to avoid the aliasing problem
(which motivated HPA to add --strict option), the receiving end,
be it git-daemon driving upload-pack or git-shell driving
receive-pack or upload-pack, can do ~user/ expansion first, then
run their policy checking on the canonicalized path before
spawning the lower level programs using the already
canonicalized path.

To also support the case where upload-pack and receive-pack are
started directly from the ssh connection, these programs need to
apply ~user/ expansion to the incoming path themselves by
default.  In order to avoid double expansion, git-daemon and
git-shell should pass --no-user-expansion flag to the lower
level programs when it starts them if we do this.

A common library that takes the path supplied from the other end
and does ~user/ expansion would be useful for the above; we can
lift that logic from Andreas' srvside_chdir().

^ permalink raw reply

* Re: LCA2006 Git/Cogito tutorial
From: Petr Baudis @ 2005-10-23 22:40 UTC (permalink / raw)
  To: Horst von Brand; +Cc: Martin Langhoff (CatalystIT), Dmitry Torokhov, git
In-Reply-To: <200510231533.j9NFXhOv019272@inti.inf.utfsm.cl>

Dear diary, on Sun, Oct 23, 2005 at 05:33:43PM CEST, I got a letter
where Horst von Brand <vonbrand@inf.utfsm.cl> told me that...
> Martin Langhoff (CatalystIT) <martin@catalyst.net.nz> wrote:
> [...]
> >     MERGE ERROR: : Not handling case  ->  ->
> 
> It happens when a new file with the same name appears in both parents. For
> example, we both see the need for a README file, and then I pull from you
> and try to merge into my version.

It certainly shouldn't happen with precisely that error message - there
should be at least something written between the arrows. And yes, there
are unhandled cases like that, as I wrote in one of my other mails.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply

* Re: LCA2006 Git/Cogito tutorial
From: Petr Baudis @ 2005-10-23 22:39 UTC (permalink / raw)
  To: Horst von Brand; +Cc: Martin Langhoff (CatalystIT), Dmitry Torokhov, git
In-Reply-To: <200510231535.j9NFZrmD019309@inti.inf.utfsm.cl>

Dear diary, on Sun, Oct 23, 2005 at 05:35:53PM CEST, I got a letter
where Horst von Brand <vonbrand@inf.utfsm.cl> told me that...
> Petr Baudis <pasky@suse.cz> wrote:
> 
> [...]
> 
> > Well, it's true that cg-Xmergefile still does not handle all merge
> > cases, but it certainly will not be silent about it, at least. ;-)
> 
> The Codeville <http://www.codeville.org> people seem to have taken a hard
> look at merging, but I don't find any clear references to their algorithm.

They are working on something much more general, basically abandoning
the three-level (RCS-like) merging model altogether and going for the
weave (SCCS-like) merging model instead. See also

	http://revctrl.org/PreciseCodevilleMerge

and short crawling around the wiki and external links should give you
pretty good idea (see especially SimpleWeaveMerge).

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply

* Re: Scribblings for a cogito/git tutorial
From: Petr Baudis @ 2005-10-23 22:36 UTC (permalink / raw)
  To: Horst von Brand; +Cc: git, Martin Langhoff (CatalystIT)
In-Reply-To: <200510212146.j9LLkun3004745@inti.inf.utfsm.cl>

Dear diary, on Fri, Oct 21, 2005 at 11:46:56PM CEST, I got a letter
where Horst von Brand <vonbrand@inf.utfsm.cl> told me that...
> I'm also thinking on changing the octopus example into one that works and
> clean up some stuff. And perhaps make Bob into a diehard git user, for
> contrast.

Nice idea to show all the angles - although for Cogito I think I will
stay with pure Cogito (wherever possible), no need to scare the users...
;-))

Dear diary, on Fri, Oct 21, 2005 at 11:56:39PM CEST, I got a letter
where Horst von Brand <vonbrand@inf.utfsm.cl> told me that...
> > > Repository of the script and supporting files is at
> > > <http://pincoya.inf.utfsm.cl/Script.git>
> 
> > Thanks, it's very nice! If you don't mind (actually, is it / can it be GPL?),
> > I added it to Cogito as Documentation/tutorial-script/ .
> 
> It seems you got the whole history of the script into cogito's history. Is
> that right?

Nope. I couldn't just merge (like gitk-in-git) since I needed to move
the files to a subdirectory, so I would have to do that manually. And I
decided to just flatten it since it was just two revisions, after all.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply

* Re: Merge failure problem with cogito: How to fixup?
From: Petr Baudis @ 2005-10-23 22:32 UTC (permalink / raw)
  To: Horst von Brand; +Cc: git
In-Reply-To: <200510231557.j9NFvptA020919@inti.inf.utfsm.cl>

Dear diary, on Sun, Oct 23, 2005 at 05:57:51PM CEST, I got a letter
where Horst von Brand <vonbrand@inf.utfsm.cl> told me that...
> When doing the following:
> 
>    mkdir /tmp/tst1
>    cd /tmp/tst1
>    echo "Initial" | cg-init 
>       
>    cd /tmp
>    cg-clone tst1 tst2
>    
>    cd /tmp/tst1
>    echo 'Hi there!' > greet
>    cg-add greet
>    cg-commit -m "Add greet"
>    
>    cd /tmp/tst2
>    echo 'Hello!' > greet
>    cg-add greet
>    cg-commit -m "Add greet"
> 
>    cg-update
> 
> I get a message to the end that the merge doesn't work, and that I have to
> fix up by hand. The resulting greet file has no merge markers, plain
> "cg-diff" is useless. How am I supposed to find out what the problem is?
> 
> Yes, "cg-diff -r origin:HEAD" does the trick, but...

Well, yes, that's one of the "unhandled merge cases". :-)

To fixup:

	<resolve the merge somehow, probably adding greet in some form>
	cg-add greet

(You should be able to cg-rm greet instead if you decide to drop the
file after all.)

This is a _trick_ and it works just because cg-add and cg-rm purely
accidentally do the right GIT commands to also resolve an index-level
merge conflict. The proper solution would be to add the proper case to
cg-Xmergefile, which should be actually pretty easy, if only someone
does it... ;-)

Ok, and cg-status should be taught about it and report "greet" somehow
as a conflict until you choose one of the versions.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply

* Re: User-relative paths
From: Junio C Hamano @ 2005-10-23 22:30 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20051023222554.GT30889@pasky.or.cz>

Petr Baudis <pasky@suse.cz> writes:

> I'm talking only about the compilation command, not about the dependency
> line.

Ah, I missed that typo.  Thanks.

^ permalink raw reply

* Re: User-relative paths
From: Petr Baudis @ 2005-10-23 22:25 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7voe5gypvi.fsf@assigned-by-dhcp.cox.net>

Dear diary, on Sun, Oct 23, 2005 at 09:50:25PM CEST, I got a letter
where Junio C Hamano <junkio@cox.net> told me that...
> Petr Baudis <pasky@suse.cz> writes:
> 
> >> diff --git a/Makefile b/Makefile
> >> index 903c57c..87188ea 100644
> >> --- a/Makefile
> >> +++ b/Makefile
> >> @@ -359,6 +362,9 @@ git-cherry-pick: git-revert
> >>  %.o: %.S
> >>  	$(CC) -o $*.o -c $(ALL_CFLAGS) $<
> >>  
> >> +$(SERVERSIDE_PROGRAMS) : git-%$X : %.o srvside-ssh.o $(LIB_FILE)
> >> +	$(CC) $(ALL_CFLAGS) -o $@ $(filter %o,$^) $(LIBS)
> >> +
> >>  git-%$X: %.o $(LIB_FILE)
> >>  	$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)
> >>  
> >
> > Why are you adding own compilation command, and why is it inconsistent
> > with the git-%$X's one?
> 
> Although I'd prefer the simplicity of putting srvside-ssh.o in
> LIB_OBJS, this is arguably defensible; it avoids relinking of
> everything else merely because srvside-ssh.c is changed.

I'm talking only about the compilation command, not about the dependency
line.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply

* Re: User-relative paths
From: Linus Torvalds @ 2005-10-23 21:30 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Andreas Ericsson, git
In-Reply-To: <7v1x2cyplw.fsf@assigned-by-dhcp.cox.net>



On Sun, 23 Oct 2005, Junio C Hamano wrote:
> 
> No, it is this one:
> 
>     http://marc.theaimsgroup.com/?l=git&m=112681457828137&w=2
> 
> But it is orthogonal to what you are doing in this patch.

Well, not necessarily.

It's quite arguable that sanity testing might be per-user and could be 
done by the shell. I'm not at all sure that srvside_chdir() should do any 
extra testing: if you have real ssh access, the user has the right to do 
anything he damn well pleases.

So it's quite possible that you should do testing in the thing that 
receives the request, ie in a restricted shell (or, as we already do, in 
git-daemon).

I tried to find my original unquote example and stupid shell, but 
couldn't.  So I wrote something untested as usual.

It's incomplete and almost certainly buggy and generally broken, but 
here's somethign that you _could_ install as "git-shell", and then put 
that as somebodys shell in /etc/passwd, and it's a start. A very rough 
start.

Somebody else gets to test it out ;)

		Linus

---
2906a25bbd1dedbd6bab9ed984a503340229b020
diff --git a/Makefile b/Makefile
index 7eacf61..34bbdb6 100644
--- a/Makefile
+++ b/Makefile
@@ -102,7 +102,7 @@ SCRIPT_PYTHON = \
 # The ones that do not have to link with lcrypto nor lz.
 SIMPLE_PROGRAMS = \
 	git-get-tar-commit-id$X git-mailinfo$X git-mailsplit$X \
-	git-stripspace$X git-var$X git-daemon$X
+	git-stripspace$X git-var$X git-daemon$X git-shell$X
 
 # ... and all the rest
 PROGRAMS = \
diff --git a/shell.c b/shell.c
new file mode 100644
index 0000000..676d398
--- /dev/null
+++ b/shell.c
@@ -0,0 +1,89 @@
+#include "cache.h"
+
+static char *dequote(char *arg)
+{
+	char *dst = arg;
+	char *src = arg;
+	char c;
+
+	if (*src != '\'')
+		return NULL;
+	for (;;) {
+		c = *++src;
+		if (!c)
+			return NULL;
+		if (c != '\'') {
+			*dst++ = c;
+			continue;
+		}
+		switch (*++src) {
+		case '\0':
+			*dst = 0;
+			return arg;
+		case '\\':
+			if (*++src == '\'' &&
+			    *++src == '\'') {
+				*dst = '\'';
+				continue;
+			}
+		/* Fallthrough */
+		default:
+			return NULL;
+		}
+	}
+}
+
+static int do_receive_pack(char *arg)
+{
+	char cwd[1000];
+	char *my_argv[4];
+
+	arg = dequote(arg);
+	if (!arg)	
+		die("bad argument");
+
+	my_argv[0] = "git-receive-pack";
+	my_argv[1] = arg;
+	my_argv[2] = NULL;
+	return execvp("git-receive-pack", my_argv);
+}
+
+static struct commands {
+	const char *name;
+	int (*exec)(char *arg);
+} cmd_list[] = {
+	{ "git-receive-pack", do_receive_pack },
+	{ NULL },
+};
+
+int main(int argc, char **argv)
+{
+	char *prog;
+	struct commands *cmd;
+
+	/* We want to see "-c cmd args", and nothing else */
+	if (argc != 3 || strcmp(argv[1], "-c"))
+		die("What do you think I am? A shell?");
+	prog = argv[2];
+	argv += 2;
+	argc -= 2;
+	for (cmd = cmd_list ; cmd->name ; cmd++) {
+		int len = strlen(cmd->name);
+		char *arg;
+		if (strncmp(cmd->name, prog, len))
+			continue;
+		arg = NULL;
+		switch (prog[len]) {
+		case '\0':
+			arg = NULL;
+			break;
+		case ' ':
+			arg = prog + len + 1;
+			break;
+		default:
+			continue;
+		}
+		exit(cmd->exec(arg));
+	}
+	die("unrecognized command '%s'", prog);
+}

^ permalink raw reply related

* Re: User-relative paths
From: Junio C Hamano @ 2005-10-23 19:56 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: git
In-Reply-To: <435B5AE0.1060400@op5.se>

Andreas Ericsson <ae@op5.se> writes:

> Junio C Hamano wrote:
>> Andreas Ericsson <ae@op5.se> writes:
>> ...
>> At one point, Linus posted an outline of "restricted login shell
>> for use with git over ssh".  I think you could start from there,
>> perhaps extend it so that it checks the binaries *and* pathnames
>> the user can specify (e.g. only under your own $HOME is allowed,
>> and no /../ in them, or something silly like that).
>>
>
> I found this in the archives:
> http://article.gmane.org/gmane.comp.version-control.git/5784/match=restricted+login
>
> Is that what you're referring to?

No, it is this one:

    http://marc.theaimsgroup.com/?l=git&m=112681457828137&w=2

But it is orthogonal to what you are doing in this patch.

> Let me know if you want things done differently.

I think srvside_chdir() should not do the userdir expansion
under --strict (otherwise you would need a matching change in
daemon.c as well, but I would rather not).

The --strict flag in upload-pack is to make sure git-daemon can
see what is being accessed and make its policy decision even
before it calls upload-pack.  In a pathological case, somebody
can create a directory "/~foo/bar/.git", where the "/~foo"
directory is different from "/home/foo", and have git-daemon
check that the former is OK and call your upload-pack.  Your
upload-pack uses srvside_chdir() and exposes /home/foo/bar/.git;
this circumvents git-daemon's policy decision, doesn't it?

I also agree with everything Pasky already said.

 * In a URL, a colon after hostname means "port number
   follows".  So it was a good intention to make these
   consistent:

        git fetch ssh://kernel.org:git
        git fetch kernel.org:git

   it should not be done.  IOW, if I wanted to use the former
   form (which I do not think I'd use myself), I should say either one
   of:

        git fetch ssh://kernel.org:~/git
        git fetch ssh://kernel.org:~junio/git

   Oh, I just noticed you do not handle the former, because you
   did not have to, but now you need to.

 * Use of "extern const char *__progname" is questionable.  I
   could be easily talked into:

    - have "extern const char *git_program_name" in cache.h or
      somewhere;

    - convert programs (gradually) to set that at the beginning
      of main();

    - update die() and error() to use that variable when
      reporting (both callers and implementation) -- this is
      optional.

^ permalink raw reply

* Re: User-relative paths
From: Junio C Hamano @ 2005-10-23 19:50 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20051023183757.GS30889@pasky.or.cz>

Petr Baudis <pasky@suse.cz> writes:

>> diff --git a/Makefile b/Makefile
>> index 903c57c..87188ea 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -359,6 +362,9 @@ git-cherry-pick: git-revert
>>  %.o: %.S
>>  	$(CC) -o $*.o -c $(ALL_CFLAGS) $<
>>  
>> +$(SERVERSIDE_PROGRAMS) : git-%$X : %.o srvside-ssh.o $(LIB_FILE)
>> +	$(CC) $(ALL_CFLAGS) -o $@ $(filter %o,$^) $(LIBS)
>> +
>>  git-%$X: %.o $(LIB_FILE)
>>  	$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)
>>  
>
> Why are you adding own compilation command, and why is it inconsistent
> with the git-%$X's one?

Although I'd prefer the simplicity of putting srvside-ssh.o in
LIB_OBJS, this is arguably defensible; it avoids relinking of
everything else merely because srvside-ssh.c is changed.

^ permalink raw reply

* Re: git-rev-list: add "--dense" flag
From: Marco Costalba @ 2005-10-23 19:30 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List

Linus Torvalds wrote:

>
>And it scales pretty well too. On the historical linux archive, which is 
>three years of history, the same thing takes me just over 12 seconds and 
>52MB, and that's for the _whole_ history. And it's not just following one 
>file: it's following that subdirectory.
>
>So it really is pretty damn cool. 
>

Yes, it is. Very powerful and useful tool indeed. IMHO kudos!

>Of course, I might have a bug somewhere, but it all _seems_ to work very 
>well indeed.
>

The only bug I found is in qgit ;-) that failed to correctly handle --dense option.

It is now fixed in my GIT archive: http://digilander.libero.it/mcostalba/qgit.git


    Marco



		
__________________________________ 
Yahoo! FareChase: Search multiple travel sites in one click.
http://farechase.yahoo.com

^ permalink raw reply

* Re: Scribblings for a cogito/git tutorial
From: Horst von Brand @ 2005-10-21 21:46 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Horst von Brand, git, Martin Langhoff (CatalystIT)
In-Reply-To: <20051021205129.GI30889@pasky.or.cz>

Petr Baudis <pasky@suse.cz> wrote:
> Dear diary, on Mon, Oct 17, 2005 at 05:04:54PM CEST, I got a letter
> where Horst von Brand <vonbrand@inf.utfsm.cl> told me that...
> > I've also been asked around here for a cogito+git tutorial, to that end
> > I've made up a script that simulates several developers interacting.
> > Hacking around is simulated by patching, ed(1) scripts (merges don't turn
> > out the same diff every time), and plain copying new files in. I've set up
> > a GPG key with an empty passphrase (comment is "Experimental") to have
> > signed tags, etc. in a convenient manner. The idea is to create interesting
> > histories (for browsing) and show off the commands in a compact way. If
> > only there was a convenient way to run a strech of the (bash) script, look
> > at the results, and then resume...
> > 
> > Comments, suggestions, patches are welcome! 
> > 
> > Repository of the script and supporting files is at
> > <http://pincoya.inf.utfsm.cl/Script.git>

> Thanks, it's very nice! If you don't mind (actually, is it / can it be GPL?),

Certainly, I realized later that I didn't clarify the license. It's on my
TODO list ;-)

I'm also thinking on changing the octopus example into one that works and
clean up some stuff. And perhaps make Bob into a diehard git user, for
contrast.

> I added it to Cogito as Documentation/tutorial-script/ .

I'm honored.
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513

^ permalink raw reply

* Re: Scribblings for a cogito/git tutorial
From: Horst von Brand @ 2005-10-21 21:56 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Horst von Brand, git, Martin Langhoff (CatalystIT)
In-Reply-To: <20051021205129.GI30889@pasky.or.cz>

Petr Baudis <pasky@suse.cz> wrote:
> Dear diary, on Mon, Oct 17, 2005 at 05:04:54PM CEST, I got a letter
> where Horst von Brand <vonbrand@inf.utfsm.cl> told me that...

[...]

> > Repository of the script and supporting files is at
> > <http://pincoya.inf.utfsm.cl/Script.git>

> Thanks, it's very nice! If you don't mind (actually, is it / can it be GPL?),
> I added it to Cogito as Documentation/tutorial-script/ .

It seems you got the whole history of the script into cogito's history. Is
that right?
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513

^ permalink raw reply

* Re: LCA2006 Git/Cogito tutorial
From: Horst von Brand @ 2005-10-23 15:33 UTC (permalink / raw)
  To: Martin Langhoff (CatalystIT); +Cc: Dmitry Torokhov, git, Petr Baudis
In-Reply-To: <4358597A.6000306@catalyst.net.nz>

Martin Langhoff (CatalystIT) <martin@catalyst.net.nz> wrote:

[...]

> If you combine the coolness of git-merge.sh with the fact that
> cg-merge right now is buggy[*]... I'm starting to rely on doing
> cg-fetch and running git-merge.sh by hand.
> 
> * I just merged your latest fixes, knowing that they'd conflict on
> * cg-fetch, but the merge didn't say a thing a bout cg-fetch, and only
> * complained like this:
> 
>     MERGE ERROR: : Not handling case  ->  ->
> 
> But there were no conflicts at all in the tree! It seems to be that
> it's dropping the upstream changes it doesn't like.

It happens when a new file with the same name appears in both parents. For
example, we both see the need for a README file, and then I pull from you
and try to merge into my version.
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513

^ permalink raw reply

* Re: LCA2006 Git/Cogito tutorial
From: Horst von Brand @ 2005-10-23 15:35 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Martin Langhoff (CatalystIT), Dmitry Torokhov, git
In-Reply-To: <20051021091551.GE30889@pasky.or.cz>

Petr Baudis <pasky@suse.cz> wrote:

[...]

> Well, it's true that cg-Xmergefile still does not handle all merge
> cases, but it certainly will not be silent about it, at least. ;-)

The Codeville <http://www.codeville.org> people seem to have taken a hard
look at merging, but I don't find any clear references to their algorithm.
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513

^ permalink raw reply

* Merge failure problem with cogito: How to fixup?
From: Horst von Brand @ 2005-10-23 15:57 UTC (permalink / raw)
  To: git

When doing the following:

   mkdir /tmp/tst1
   cd /tmp/tst1
   echo "Initial" | cg-init 
      
   cd /tmp
   cg-clone tst1 tst2
   
   cd /tmp/tst1
   echo 'Hi there!' > greet
   cg-add greet
   cg-commit -m "Add greet"
   
   cd /tmp/tst2
   echo 'Hello!' > greet
   cg-add greet
   cg-commit -m "Add greet"

   cg-update

I get a message to the end that the merge doesn't work, and that I have to
fix up by hand. The resulting greet file has no merge markers, plain
"cg-diff" is useless. How am I supposed to find out what the problem is?

Yes, "cg-diff -r origin:HEAD" does the trick, but...
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513

^ permalink raw reply

* Re: User-relative paths (was: Server side programs)
From: Petr Baudis @ 2005-10-23 18:37 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: git
In-Reply-To: <435B5AE0.1060400@op5.se>

Dear diary, on Sun, Oct 23, 2005 at 11:41:52AM CEST, I got a letter
where Andreas Ericsson <ae@op5.se> told me that...
> Anyways, the attached patch does this. I've tested all the various 
> syntaxes and they work as expected. rsync, http and local files take the 
> same syntax as before. I haven't added support for user-relative paths 
> to the git-daemon (can't see the point, really) although that can be 
> done easily enough.

It would be useful to add a [PATCH] tag to subject when you submit a
patch, so that we notice it better. ;-)

You don't update the documentation even though there seem to be some
syntactic changes. You should at least update

	Documentation/pull-fetch-param.txt

Also before Junio asks you, in the followup patches, you might want to
sign off the patch if you want it integrated.

> diff --git a/Makefile b/Makefile
> index 903c57c..87188ea 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -359,6 +362,9 @@ git-cherry-pick: git-revert
>  %.o: %.S
>  	$(CC) -o $*.o -c $(ALL_CFLAGS) $<
>  
> +$(SERVERSIDE_PROGRAMS) : git-%$X : %.o srvside-ssh.o $(LIB_FILE)
> +	$(CC) $(ALL_CFLAGS) -o $@ $(filter %o,$^) $(LIBS)
> +
>  git-%$X: %.o $(LIB_FILE)
>  	$(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS)
>  

Why are you adding own compilation command, and why is it inconsistent
with the git-%$X's one?

> diff --git a/connect.c b/connect.c
> index b171c5d..0d78b3e 100644
> --- a/connect.c
> +++ b/connect.c
> @@ -436,33 +436,44 @@ static int git_tcp_connect(int fd[2], co
> +	/* leading colon marks relative path for ssh.
> +	 * Check for host == url and default to PROTO_SSH to allow
> +	 *   $ git fetch kernel.org:git
> +	 */
> +	if(ptr && (!path || ptr < path)) {
> +		if(host == url)
> +			protocol = PROTO_SSH;
> +
> +		if(protocol == PROTO_SSH) {
> +			*ptr = '\0';
> +			path = ptr + 1;
>  		}
>  	}

If I understand this right,

	ssh://foo.bar:baz/quux

will make foo.bar the host and baz/quux the path. Please, do NOT do
this! It is supposed to be a URL, dammit! And you know, URLs have
defined _syntax_, and that's important at least every time the URL gets
out of GIT's context. Or stop it calling URL altogether, to prevent any
confusion. But in URLs, the space between : and / is a port definition.
See also RFC3986 (aka STD066) and RFC2718.

Thanks.

> diff --git a/receive-pack.c b/receive-pack.c
> index 8f157bc..9a040ff 100644
> --- a/receive-pack.c
> +++ b/receive-pack.c
> @@ -265,18 +267,9 @@ int main(int argc, char **argv)
>  	if (!dir)
>  		usage(receive_pack_usage);
>  
> -	/* chdir to the directory. If that fails, try appending ".git" */
> -	if (chdir(dir) < 0) {
> -		if (chdir(mkpath("%s.git", dir)) < 0)
> -			die("unable to cd to %s", dir);
> -	}
> -
> -	/* If we have a ".git" directory, chdir to it */
> -	chdir(".git");
> -	putenv("GIT_DIR=.");
> +	/* Find the right directory */
> +	srvside_chdir(dir, 0);
>  
> -	if (access("objects", X_OK) < 0 || access("refs/heads", X_OK) < 0)
> -		die("%s doesn't appear to be a git directory", dir);
>  	write_head_info();
>  
>  	/* EOF */

No srvside_chdir() declaration?

> diff --git a/srvside-ssh.c b/srvside-ssh.c
> new file mode 100644
> index 0000000..0ed5d30
> --- /dev/null
> +++ b/srvside-ssh.c
> @@ -0,0 +1,63 @@
> +#include "cache.h"
> +#include <unistd.h>
> +#include <pwd.h>
> +
> +extern const char *__progname;

How portable is this? It appears that no standard really defines this,
and Google faintly hints at least some Cygwin-related problems...

> diff --git a/upload-pack.c b/upload-pack.c
> index accdba6..356c9b1 100644
> --- a/upload-pack.c
> +++ b/upload-pack.c
> @@ -5,6 +5,7 @@
>  #include "object.h"
>  
>  static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=nn] <dir>";
> +extern void srvside_chdir(const char *path, int strict);
>  
>  #define MAX_HAS 256
>  #define MAX_NEEDS 256

What about a .h file?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which
it doesn't.

^ permalink raw reply

* Re: git and gitweb inconsistencies
From: Sven Verdoolaege @ 2005-10-23 18:28 UTC (permalink / raw)
  To: Chris Shoemaker; +Cc: git, Matthias Urlichs
In-Reply-To: <20051023173055.GA3019@pe.Belkin>

On Sun, Oct 23, 2005 at 01:30:55PM -0400, Chris Shoemaker wrote:
> I foolishly assumed that the second time I ran git-cvsimport, with -C
> /pub/scm/project/ it would be able to detect that I was using the
> stand-alone GIT-DIR.  But, it obviously didn't.  I guess the solution
> is use specify GIT_DIR everytime I run git-cvstimport.

Since many of the core git tools try to detect the actual git dir,
it might not be a bad idea for cvsimport to do this as well.
It probably also shouldn't create a new git repository if the -i
option has been specified.

> So, it seems that git-web.cgi detects and prefers the stand-alone
> directory structure, because I specify it in the projects_list file,
> while git-cat-file, and git-update-ref default to using .git.

gitweb just sets GIT_DIR and then the core git tools won't guess.

skimo

^ permalink raw reply

* Re: git and gitweb inconsistencies
From: Chris Shoemaker @ 2005-10-23 17:30 UTC (permalink / raw)
  To: git; +Cc: skimo
In-Reply-To: <20051023115939.GG8383MdfPADPa@greensroom.kotnet.org>

On Sun, Oct 23, 2005 at 01:59:39PM +0200, Sven Verdoolaege wrote:
> On Sat, Oct 22, 2005 at 08:14:12PM -0400, Chris Shoemaker wrote:
> > A few days later, I ran git-cvsimport again, with -i.  This imported
> > just the recent changes, but the view from gitweb didn't change.  :(
> 
> Are you sure you didn't just create a new import *inside* the old import ?
> Do you have, say, both an 'objects' and a '.git/objects' directory ?

OH!  You, sir, DO have a crystal ball.  :) 

I foolishly assumed that the second time I ran git-cvsimport, with -C
/pub/scm/project/ it would be able to detect that I was using the
stand-alone GIT-DIR.  But, it obviously didn't.  I guess the solution
is use specify GIT_DIR everytime I run git-cvstimport.

So, it seems that git-web.cgi detects and prefers the stand-alone
directory structure, because I specify it in the projects_list file,
while git-cat-file, and git-update-ref default to using .git.

> 
> > $ echo `git-rev-list tip --max-count=1` > refs/heads/mytest
> > $ git-cat-file -t `cat refs/heads/mytest`
> 
> That should be
> 
> git-update-ref refs/heads/mytest tip
> (the new head will appear in .git/refs/heads/mytest, 
> unless you've set GIT_DIR)
> git-cat-file -t mytest

Ah, and if I'd used that command, I would have realized something was
wrong when mytest *didn't* appear in refs/heads, but rather
.git/refs/heads.

Thanks for thinking creatively about how I could have messed it up!

-chris

> 
> 
> skimo

^ permalink raw reply

* Re: [gitweb PATCH] add a 'diff to parent' option in the file history display
From: Brad Roberts @ 2005-10-23 17:13 UTC (permalink / raw)
  To: git
In-Reply-To: <Pine.LNX.4.44.0510230815570.2284-100000@bellevue.puremagic.com>

And of course I flub another patch.. the first new line there needs a
trailing '.'.  I've checked in that change to the repository below.

Also, both of these are on the 'brad-master' branch, not 'master'.

On Sun, 23 Oct 2005, Brad Roberts wrote:

> Date: Sun, 23 Oct 2005 08:25:05 -0700 (PDT)
> From: Brad Roberts <braddr@puremagic.com>
> To: git@vger.kernel.org
> Subject: [gitweb PATCH] add a 'diff to parent' option in the file history
>     display
>
> I'm not sure how well this plays with multiple parent merges or anything
> complicated.  It seems to work well on a converted cvs archive.
>
> Pullable from:  git://cvs.puremagic.com/git/gitweb.git
>
> ---------------------
> add a 'diff to parent' option in the file history display
>
> Signed-off-by: Brad Roberts <braddr@puremagic.com>
> ---
>
>  gitweb.cgi |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
>
> 2539b424d62cc2ab060c5d2fa9525a6b6f8df7e5
> diff --git a/gitweb.cgi b/gitweb.cgi
> --- a/gitweb.cgi
> +++ b/gitweb.cgi
> @@ -2054,6 +2054,9 @@ sub git_history {
>  				print " | " .
>  				$cgi->a({-href => "$my_uri?p=$project;a=blobdiff;h=$blob;hp=$blob_parent;hb=$commit;f=$file_name"},
>  				"diff to current");
> +				print " | "
> +				$cgi->a({-href => "$my_uri?p=$project;a=blobdiff;h=$blob_parent;hp=$3;hb=$commit;f=$file_name"},
> +				"diff to parent");
>  			}
>  			print "</td>\n" .
>  			      "</tr>\n";
>
>
>
> -
> 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] This commit implements git-mv
From: Josef Weidendorfer @ 2005-10-23 16:15 UTC (permalink / raw)
  To: junkio; +Cc: git

It superceeds git-rename by adding functionality to move
multiple files, directories or symlinks into another directory.
It also provides according documentation.

The implementation renames multiple files, using the arguments
from the command line to produce an array of sources and destinations.
In a first pass, all requested renames are checked for errors, and
overwriting of existing files is only allowed with '-f'.
The actual renaming is done in a second pass.
This ensures that any error condition is checked before anything is
changed.

Signed-off-by: Josef Weidendorfer <Josef.Weidendorfer@gmx.de>

---
The recent request on the list for "mv" in GIT reminded me about
an addition to git-rename I made a week ago. I renamed it to
"git-mv" and added some documentation.

If this works, we can remove git-rename sometimes in the future.

I should complement this command with tests. Also, a nice addition
would be to support an interactive mode like 'mv', by asking if
files should be overwritten.

By the way, it also checks for a request to move a directory into
itself, which of course is an error.

Option "-k" is good for this:
E.g. a "git-mv -k * dir" moves all revision controlled files and
directories (but not "dir"!) into "dir". "-k" makes sure that
the errors (trying to move "dir" into itself, or move files
without revision control around) will not terminate the command
but silently ignored and skipped.
"-k" was taken from "make": Continue even on an error.

Josef

 Documentation/git-mv.txt |   51 +++++++++++++
 Makefile                 |    2 
 git-mv.perl              |  185 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 237 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/git-mv.txt
 create mode 100755 git-mv.perl

applies-to: b9f56dae60decf015079f5feef4544e7177b143a
0baacba7907046796e5a15eb2b191c1e2cb48793
diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt
new file mode 100644
index 0000000..f2d5882
--- /dev/null
+++ b/Documentation/git-mv.txt
@@ -0,0 +1,51 @@
+git-mv(1)
+=========
+
+NAME
+----
+git-mv - Script used to move or rename a file, directory or symlink.
+
+
+SYNOPSIS
+--------
+'git-mv' [-f] [-n] <source> <destination>
+'git-mv' [-f] [-k] [-n] <source> ... <destination directory>
+
+DESCRIPTION
+-----------
+This script is used to move or rename a file, directory or symlink.
+In the first form, it renames <source>, which must exist and be either
+a file, symlink or directory, to <destination>, which must not exist.
+In the second form, the last argument has to be an existing
+directory; the given sources will be moved into this directory.
+
+The index is updated after successful completion, but the change must still be
+committed.
+
+OPTIONS
+-------
+-f::
+	Force renaming or moving even targets exist
+-k::
+        Skip move or rename actions which would lead to an error
+	condition. An error happens when a source is neither existing nor
+        controlled by GIT, or when it would overwrite an existing
+        file unless '-f' is given.
+-n::
+	Do nothing; only show what would happen
+
+
+Author
+------
+Written by Linus Torvalds <torvalds@osdl.org>
+Rewritten by Ryan Anderson <ryan@michonline.com>
+Move functionality added by Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+
+Documentation
+--------------
+Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
+
+GIT
+---
+Part of the gitlink:git[7] suite
+
diff --git a/Makefile b/Makefile
index 5ee72bc..b43c170 100644
--- a/Makefile
+++ b/Makefile
@@ -94,7 +94,7 @@ SCRIPT_SH = \
 SCRIPT_PERL = \
 	git-archimport.perl git-cvsimport.perl git-relink.perl \
 	git-rename.perl git-shortlog.perl git-fmt-merge-msg.perl \
-	git-findtags.perl git-svnimport.perl
+	git-findtags.perl git-svnimport.perl git-mv.perl
 
 SCRIPT_PYTHON = \
 	git-merge-recursive.py
diff --git a/git-mv.perl b/git-mv.perl
new file mode 100755
index 0000000..28bced9
--- /dev/null
+++ b/git-mv.perl
@@ -0,0 +1,185 @@
+#!/usr/bin/perl
+#
+# Copyright 2005, Ryan Anderson <ryan@michonline.com>
+#                 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
+#
+# This file is licensed under the GPL v2, or a later version
+# at the discretion of Linus Torvalds.
+
+
+use warnings;
+use strict;
+use Getopt::Std;
+
+sub usage() {
+	print <<EOT;
+$0 [-f] [-n] <source> <dest>
+$0 [-f] [-k] [-n] <source> ... <dest directory>
+
+In the first form, source must exist and be either a file,
+symlink or directory, dest must not exist. It renames source to dest.
+In the second form, the last argument has to be an existing
+directory; the given sources will be moved into this directory.
+
+Updates the git cache to reflect the change.
+Use "git commit" to make the change permanently.
+
+Options:
+  -f   Force renaming/moving, even if target exists
+  -k   Continue on error by skipping
+       not-existing or not revision-controlled source
+  -n   Do nothing; show what would happen
+EOT
+	exit(1);
+}
+
+# Sanity checks:
+my $GIT_DIR = $ENV{'GIT_DIR'} || ".git";
+
+unless ( -d $GIT_DIR && -d $GIT_DIR . "/objects" && 
+	-d $GIT_DIR . "/objects/" && -d $GIT_DIR . "/refs") {
+    print "Git repository not found.";
+    usage();
+}
+
+
+our ($opt_n, $opt_f, $opt_h, $opt_k, $opt_v);
+getopts("hnfkv") || usage;
+usage() if $opt_h;
+@ARGV >= 1 or usage;
+
+my (@srcArgs, @dstArgs, @srcs, @dsts);
+my ($src, $dst, $base, $dstDir);
+
+my $argCount = scalar @ARGV;
+if (-d $ARGV[$argCount-1]) {
+	$dstDir = $ARGV[$argCount-1];
+	@srcArgs = @ARGV[0..$argCount-2];
+	
+	foreach $src (@srcArgs) {
+		$base = $src;
+		$base =~ s/^.*\///;
+		$dst = "$dstDir/". $base;
+		push @dstArgs, $dst;
+	}
+}
+else {
+    if ($argCount != 2) {
+	print "Error: moving to directory '"
+	    . $ARGV[$argCount-1]
+	    . "' not possible; not exisiting\n";
+	usage;
+    }
+    @srcArgs = ($ARGV[0]);
+    @dstArgs = ($ARGV[1]);
+    $dstDir = "";
+}
+
+my (@allfiles,@srcfiles,@dstfiles);
+my $safesrc;
+my %overwritten;
+
+$/ = "\0";
+open(F,"-|","git-ls-files","-z")
+        or die "Failed to open pipe from git-ls-files: " . $!;
+
+@allfiles = map { chomp; $_; } <F>;
+close(F);
+
+
+my ($i, $bad);
+while(scalar @srcArgs > 0) {
+    $src = shift @srcArgs;
+    $dst = shift @dstArgs;
+    $bad = "";
+
+    if ($opt_v) {
+	print "Checking rename of '$src' to '$dst'\n";
+    }
+
+    unless (-f $src || -l $src || -d $src) {
+	$bad = "bad source '$src'";
+    }
+
+    $overwritten{$dst} = 0;
+    if (($bad eq "") && -e $dst) {
+	$bad = "destination '$dst' already exists";
+	if (-f $dst && $opt_f) {
+	    print "Warning: $bad; will overwrite!\n";
+	    $bad = "";
+	    $overwritten{$dst} = 1;
+	}
+    }
+    
+    if (($bad eq "") && ($src eq $dstDir)) {
+	$bad = "can not move directory '$src' into itself";
+    }
+
+    if ($bad eq "") {
+	$safesrc = quotemeta($src);
+	@srcfiles = grep /^$safesrc(\/|$)/, @allfiles;
+        if (scalar @srcfiles == 0) {
+	    $bad = "'$src' not under version control";
+	}
+    }
+
+    if ($bad ne "") {
+	if ($opt_k) {
+	    print "Warning: $bad; skipping\n";
+	    next;
+	}
+	print "Error: $bad\n";
+	usage();
+    }
+    push @srcs, $src;
+    push @dsts, $dst;
+}
+
+# Final pass: rename/move
+my (@deletedfiles,@addedfiles,@changedfiles);
+while(scalar @srcs > 0) {
+    $src = shift @srcs;
+    $dst = shift @dsts;
+
+    if ($opt_n || $opt_v) { print "Renaming $src to $dst\n"; }
+    if (!$opt_n) {
+	rename($src,$dst)
+	    or die "rename failed: $!";
+    }
+
+    $safesrc = quotemeta($src);
+    @srcfiles = grep /^$safesrc(\/|$)/, @allfiles;
+    @dstfiles = @srcfiles;
+    s/^$safesrc(\/|$)/$dst$1/ for @dstfiles;
+
+    push @deletedfiles, @srcfiles;
+    if (scalar @srcfiles == 1) {
+	if ($overwritten{$dst} ==1) {
+	    push @changedfiles, $dst;
+	} else {
+	    push @addedfiles, $dst;
+	}
+    }
+    else {
+	push @addedfiles, @dstfiles;
+    }
+}
+
+if ($opt_n) {
+	print "Changed  : ". join(", ", @changedfiles) ."\n";
+	print "Adding   : ". join(", ", @addedfiles) ."\n";
+	print "Deleting : ". join(", ", @deletedfiles) ."\n";
+	exit(1);
+}
+	
+my $rc;
+if (scalar @changedfiles >0) {
+	$rc = system("git-update-index","--",@changedfiles);
+	die "git-update-index failed to update changed files with code $?\n" if $rc;
+}
+if (scalar @addedfiles >0) {
+	$rc = system("git-update-index","--add","--",@addedfiles);
+	die "git-update-index failed to add new names with code $?\n" if $rc;
+}
+$rc = system("git-update-index","--remove","--",@deletedfiles);
+die "git-update-index failed to remove old names with code $?\n" if $rc;
---
0.99.8.GIT

^ 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