Git development
 help / color / mirror / Atom feed
* Re: GIT on MinGW problem
From: Junio C Hamano @ 2007-05-12  1:17 UTC (permalink / raw)
  To: Aaron Gray; +Cc: Git Mailing List
In-Reply-To: <1dbc01c79432$b4400a80$0200a8c0@AMD2500>

"Aaron Gray" <angray@beeb.net> writes:

> Hello,
>
> I have installed the git-1.5.1-1.mingw.exe from
> http://lilypond.org/git/binaries/mingw/.
>
> On typing 'git' I get a message box saying :-
>
>        The procedure entry point libiconv could not be located in the
> dynamic link library libiconv-2.dll.
>
> I cannot seem to find libiconv-2.dll anywhere either.
>
> Hope you can help.
>
> Many thanks in advance,
>
> Aaron

Even myself (who does not have anything to do with Windows
machines) remembers seeing this exact thing in the past 12
hours:

	article.gmane.org/gmane.comp.version-control.git/46962

Please check the archive before asking.  Thanks.

^ permalink raw reply

* Subproject clones
From: Amos Waterland @ 2007-05-12  1:16 UTC (permalink / raw)
  To: git

The logic in t3040-subprojects-basic.sh assumes that comparing the
output of 'git-ls-files -s' when run in the original superproject and
when run in the cloned superproject is a good test that cloning worked.

However, the output of git-ls-files does not include the files in
subprojects, so this test passes, even though the clone contains only
the directories of the subprojects and none of their containing files 
or .git subdirectories.

In other words, given this:

 superproject
  sub1
   Makefile
  sub2
   Makefile

when somebody does `git-clone superproject', I believe they expect to
get the same tree.  Instead, they get this:

 superproject
  sub1
  sub2

Note that `git-clone superproject/sub1` works as expected, but this
sequence fails:

 git-clone superproject foo 
 cd foo
 git-clone ../superproject/sub1

As does this sequence:

 git-clone superproject foo 
 cd foo/sub1
 git-pull ../superproject/sub1

So there is no way that I can see to actually clone a project that has
subprojects.

Is this intentional?  Shouldn't clone get the entire superproject?

^ permalink raw reply

* Re: Subproject clones
From: Junio C Hamano @ 2007-05-12  1:26 UTC (permalink / raw)
  To: Amos Waterland; +Cc: git
In-Reply-To: <20070512011600.GA24354@us.ibm.com>

apw@us.ibm.com (Amos Waterland) writes:

> Is this intentional?  Shouldn't clone get the entire superproject?

Yes.  As 1.5.2 draft release notes and my response to somebody
else last night mentioned, the plumbing level subproject support
does _NOT_ recurse into subproject and this is deliberate.

^ permalink raw reply

* Re: Subproject clones
From: Junio C Hamano @ 2007-05-12  1:32 UTC (permalink / raw)
  To: Amos Waterland; +Cc: git
In-Reply-To: <7vr6pm7ry4.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> writes:

> apw@us.ibm.com (Amos Waterland) writes:
>
>> Is this intentional?  Shouldn't clone get the entire superproject?
>
> Yes.  As 1.5.2 draft release notes and my response to somebody
> else last night mentioned, the plumbing level subproject support
> does _NOT_ recurse into subproject and this is deliberate.

Namely:

    http://article.gmane.org/gmane.comp.version-control.git/46934
    http://article.gmane.org/gmane.comp.version-control.git/46940

^ permalink raw reply

* Re: how to set up e-mail notification?
From: Julian Phillips @ 2007-05-12  1:35 UTC (permalink / raw)
  To: Oliver Kullmann; +Cc: git
In-Reply-To: <20070511195539.GF3491@cs-wsok.swansea.ac.uk>

On Fri, 11 May 2007, Oliver Kullmann wrote:

> Hello,
>
> I have set up a Git repository as a shared repository as described in
> the CVS-to-Git conversion manual.
>
> Now I want this shared Git repository to send out notification e-mails
> after commits, simulating what with CVS was achieved by
> adding to CVSROOT/loginfo the lines

...

> Now I would guess many others have already solved that task, and so I would
> be glad it they could tell me such a little script (standard Linux environment).

There's one in the standard git source tree: 
contrib/hooks/post-receive-email

never used it myself ...

-- 
Julian

  ---
Zoe: "Are those grenades?"

Jayne: "Cap'n doesn't want 'em."

Zoe: "We're robbing the place.  We're not occupying it."

^ permalink raw reply

* Re: Anyone running GIT on native Windows
From: Aaron Gray @ 2007-05-12  2:23 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git
In-Reply-To: <46449B0D.5FCD66F1@eudaptics.com>

> Han-Wen Nienhuys wrote:
>> http://lilypond.org/git/binaries/mingw/git-1.5.1-1.mingw.exe
>
> This resulted in a mostly working git toolset after I've done this in
> addition to installing it:
>
> - Installed MSYS (of course ;)
> - Install libiconv-2.dll, which can be found in
> diffutils-2.8.7-1-dep.zip from
> http://sourceforge.net/project/showfiles.php?group_id=2435 (available in
> Section Snapshot->MSYS) (rename libiconv2.dll to libiconv-2.dll)
> - Set the path to MSYS and Git manually.

This direct link is better. The above link does not take you to the correct 
place.

http://sourceforge.net/project/downloading.php?group_id=23617&use_mirror=kent&filename=diffutils-2.8.7-1-dep.zip&19135304

> For extra bonus points, I should also have installed
> bash-3.1-MSYS-1.0.11-snapshot.tar.bz2 (without which 'git am' fails) and
> msysDTK-1.0.1.exe for ssh and perl, but I haven't.
>
> gitk and git-gui are untested; they need tcltk-8.4.1-1.exe, of course.

Got GIT :)

Cheers,

Aaron

^ permalink raw reply

* Re: GIT on MinGW problem
From: Aaron Gray @ 2007-05-12  2:25 UTC (permalink / raw)
  To: Git Mailing List
In-Reply-To: <7vveey7scg.fsf@assigned-by-dhcp.cox.net>

>> I cannot seem to find libiconv-2.dll anywhere either.
>
> Even myself (who does not have anything to do with Windows
> machines) remembers seeing this exact thing in the past 12
> hours:
>
> article.gmane.org/gmane.comp.version-control.git/46962
>
> Please check the archive before asking.  Thanks.
>

Sorry.

The correct link is :-

http://sourceforge.net/project/downloading.php?group_id=23617&use_mirror=kent&filename=diffutils-2.8.7-1-dep.zip&19135304

renamed libiconv2.dll to libiconv-2.dll

Aaron 

^ permalink raw reply

* [PATCH 0/3] Remotes library, take 3
From: Daniel Barkalow @ 2007-05-12  2:39 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

This series is the same as the previous version, except that it matches 
the current behavior of builtin-push with respect to treating names as 
literal URIs.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* [PATCH 1/3] Move remote parsing into a library file out of builtin-push.
From: Daniel Barkalow @ 2007-05-12  2:39 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

The new parser is different from the one in builtin-push in two ways:
the default is to use the current branch's remote, if there is one,
before "origin"; and config is used in preference to remotes.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
---
 Makefile       |    5 +-
 builtin-push.c |  190 ++++++-----------------------------------------------
 remote.c       |  203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 remote.h       |   18 +++++
 4 files changed, 244 insertions(+), 172 deletions(-)
 create mode 100644 remote.c
 create mode 100644 remote.h

diff --git a/Makefile b/Makefile
index 7cf146b..134fbd2 100644
--- a/Makefile
+++ b/Makefile
@@ -296,7 +296,8 @@ LIB_H = \
 	diff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.h \
 	run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
 	tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
-	utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h mailmap.h
+	utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
+	mailmap.h remote.h
 
 DIFF_OBJS = \
 	diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -318,7 +319,7 @@ LIB_OBJS = \
 	write_or_die.o trace.o list-objects.o grep.o match-trees.o \
 	alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
 	color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
-	convert.o attr.o decorate.o progress.o mailmap.o
+	convert.o attr.o decorate.o progress.o mailmap.o remote.o
 
 BUILTIN_OBJS = \
 	builtin-add.o \
diff --git a/builtin-push.c b/builtin-push.c
index cb78401..0e602f3 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -5,17 +5,13 @@
 #include "refs.h"
 #include "run-command.h"
 #include "builtin.h"
-
-#define MAX_URI (16)
+#include "remote.h"
 
 static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
 
 static int all, tags, force, thin = 1, verbose;
 static const char *receivepack;
 
-#define BUF_SIZE (2084)
-static char buffer[BUF_SIZE];
-
 static const char **refspec;
 static int refspec_nr;
 
@@ -137,175 +133,29 @@ static void set_refspecs(const char **refs, int nr)
 	expand_refspecs();
 }
 
-static int get_remotes_uri(const char *repo, const char *uri[MAX_URI])
-{
-	int n = 0;
-	FILE *f = fopen(git_path("remotes/%s", repo), "r");
-	int has_explicit_refspec = refspec_nr || all || tags;
-
-	if (!f)
-		return -1;
-	while (fgets(buffer, BUF_SIZE, f)) {
-		int is_refspec;
-		char *s, *p;
-
-		if (!prefixcmp(buffer, "URL:")) {
-			is_refspec = 0;
-			s = buffer + 4;
-		} else if (!prefixcmp(buffer, "Push:")) {
-			is_refspec = 1;
-			s = buffer + 5;
-		} else
-			continue;
-
-		/* Remove whitespace at the head.. */
-		while (isspace(*s))
-			s++;
-		if (!*s)
-			continue;
-
-		/* ..and at the end */
-		p = s + strlen(s);
-		while (isspace(p[-1]))
-			*--p = 0;
-
-		if (!is_refspec) {
-			if (n < MAX_URI)
-				uri[n++] = xstrdup(s);
-			else
-				error("more than %d URL's specified, ignoring the rest", MAX_URI);
-		}
-		else if (is_refspec && !has_explicit_refspec) {
-			if (!wildcard_ref(s))
-				add_refspec(xstrdup(s));
-		}
-	}
-	fclose(f);
-	if (!n)
-		die("remote '%s' has no URL", repo);
-	return n;
-}
-
-static const char **config_uri;
-static const char *config_repo;
-static int config_repo_len;
-static int config_current_uri;
-static int config_get_refspecs;
-static int config_get_receivepack;
-
-static int get_remote_config(const char* key, const char* value)
-{
-	if (!prefixcmp(key, "remote.") &&
-	    !strncmp(key + 7, config_repo, config_repo_len)) {
-		if (!strcmp(key + 7 + config_repo_len, ".url")) {
-			if (config_current_uri < MAX_URI)
-				config_uri[config_current_uri++] = xstrdup(value);
-			else
-				error("more than %d URL's specified, ignoring the rest", MAX_URI);
-		}
-		else if (config_get_refspecs &&
-			 !strcmp(key + 7 + config_repo_len, ".push")) {
-			if (!wildcard_ref(value))
-				add_refspec(xstrdup(value));
-		}
-		else if (config_get_receivepack &&
-			 !strcmp(key + 7 + config_repo_len, ".receivepack")) {
-			if (!receivepack) {
-				char *rp = xmalloc(strlen(value) + 16);
-				sprintf(rp, "--receive-pack=%s", value);
-				receivepack = rp;
-			} else
-				error("more than one receivepack given, using the first");
-		}
-	}
-	return 0;
-}
-
-static int get_config_remotes_uri(const char *repo, const char *uri[MAX_URI])
-{
-	config_repo_len = strlen(repo);
-	config_repo = repo;
-	config_current_uri = 0;
-	config_uri = uri;
-	config_get_refspecs = !(refspec_nr || all || tags);
-	config_get_receivepack = (receivepack == NULL);
-
-	git_config(get_remote_config);
-	return config_current_uri;
-}
-
-static int get_branches_uri(const char *repo, const char *uri[MAX_URI])
-{
-	const char *slash = strchr(repo, '/');
-	int n = slash ? slash - repo : 1000;
-	FILE *f = fopen(git_path("branches/%.*s", n, repo), "r");
-	char *s, *p;
-	int len;
-
-	if (!f)
-		return 0;
-	s = fgets(buffer, BUF_SIZE, f);
-	fclose(f);
-	if (!s)
-		return 0;
-	while (isspace(*s))
-		s++;
-	if (!*s)
-		return 0;
-	p = s + strlen(s);
-	while (isspace(p[-1]))
-		*--p = 0;
-	len = p - s;
-	if (slash)
-		len += strlen(slash);
-	p = xmalloc(len + 1);
-	strcpy(p, s);
-	if (slash)
-		strcat(p, slash);
-	uri[0] = p;
-	return 1;
-}
-
-/*
- * Read remotes and branches file, fill the push target URI
- * list.  If there is no command line refspecs, read Push: lines
- * to set up the *refspec list as well.
- * return the number of push target URIs
- */
-static int read_config(const char *repo, const char *uri[MAX_URI])
-{
-	int n;
-
-	if (*repo != '/') {
-		n = get_remotes_uri(repo, uri);
-		if (n > 0)
-			return n;
-
-		n = get_config_remotes_uri(repo, uri);
-		if (n > 0)
-			return n;
-
-		n = get_branches_uri(repo, uri);
-		if (n > 0)
-			return n;
-	}
-
-	uri[0] = repo;
-	return 1;
-}
-
 static int do_push(const char *repo)
 {
-	const char *uri[MAX_URI];
-	int i, n, errs;
+	int i, errs;
 	int common_argc;
 	const char **argv;
 	int argc;
+	struct remote *remote = remote_get(repo);
 
-	n = read_config(repo, uri);
-	if (n <= 0)
+	if (!remote)
 		die("bad repository '%s'", repo);
 
+	if (remote->receivepack) {
+		char *rp = xmalloc(strlen(remote->receivepack) + 16);
+		sprintf(rp, "--receive-pack=%s", remote->receivepack);
+		receivepack = rp;
+	}
+	if (!refspec && !all && !tags && remote->push_refspec_nr) {
+		for (i = 0; i < remote->push_refspec_nr; i++) {
+			if (!wildcard_ref(remote->push_refspec[i]))
+				add_refspec(remote->push_refspec[i]);
+		}
+	}
+
 	argv = xmalloc((refspec_nr + 10) * sizeof(char *));
 	argv[0] = "dummy-send-pack";
 	argc = 1;
@@ -318,12 +168,12 @@ static int do_push(const char *repo)
 	common_argc = argc;
 
 	errs = 0;
-	for (i = 0; i < n; i++) {
+	for (i = 0; i < remote->uri_nr; i++) {
 		int err;
 		int dest_argc = common_argc;
 		int dest_refspec_nr = refspec_nr;
 		const char **dest_refspec = refspec;
-		const char *dest = uri[i];
+		const char *dest = remote->uri[i];
 		const char *sender = "send-pack";
 		if (!prefixcmp(dest, "http://") ||
 		    !prefixcmp(dest, "https://"))
@@ -341,7 +191,7 @@ static int do_push(const char *repo)
 		if (!err)
 			continue;
 
-		error("failed to push to '%s'", uri[i]);
+		error("failed to push to '%s'", remote->uri[i]);
 		switch (err) {
 		case -ERR_RUN_COMMAND_FORK:
 			error("unable to fork for %s", sender);
@@ -362,7 +212,7 @@ static int do_push(const char *repo)
 int cmd_push(int argc, const char **argv, const char *prefix)
 {
 	int i;
-	const char *repo = "origin";	/* default repository */
+	const char *repo = NULL;	/* default repository */
 
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
diff --git a/remote.c b/remote.c
new file mode 100644
index 0000000..1dd2e77
--- /dev/null
+++ b/remote.c
@@ -0,0 +1,203 @@
+#include "cache.h"
+#include "remote.h"
+#include "refs.h"
+
+static struct remote **remotes;
+static int allocated_remotes;
+
+#define BUF_SIZE (2084)
+static char buffer[BUF_SIZE];
+
+static void add_push_refspec(struct remote *remote, const char *ref)
+{
+	int nr = remote->push_refspec_nr + 1;
+	remote->push_refspec =
+		xrealloc(remote->push_refspec, nr * sizeof(char *));
+	remote->push_refspec[nr-1] = ref;
+	remote->push_refspec_nr = nr;
+}
+
+static void add_uri(struct remote *remote, const char *uri)
+{
+	int nr = remote->uri_nr + 1;
+	remote->uri =
+		xrealloc(remote->uri, nr * sizeof(char *));
+	remote->uri[nr-1] = uri;
+	remote->uri_nr = nr;
+}
+
+static struct remote *make_remote(const char *name, int len)
+{
+	int i, empty = -1;
+
+	for (i = 0; i < allocated_remotes; i++) {
+		if (!remotes[i]) {
+			if (empty < 0)
+				empty = i;
+		} else {
+			if (len ? (!strncmp(name, remotes[i]->name, len) &&
+				   !remotes[i]->name[len]) :
+			    !strcmp(name, remotes[i]->name))
+				return remotes[i];
+		}
+	}
+
+	if (empty < 0) {
+		empty = allocated_remotes;
+		allocated_remotes += allocated_remotes ? allocated_remotes : 1;
+		remotes = xrealloc(remotes,
+				   sizeof(*remotes) * allocated_remotes);
+		memset(remotes + empty, 0,
+		       (allocated_remotes - empty) * sizeof(*remotes));
+	}
+	remotes[empty] = xcalloc(1, sizeof(struct remote));
+	if (len)
+		remotes[empty]->name = xstrndup(name, len);
+	else
+		remotes[empty]->name = xstrdup(name);
+	return remotes[empty];
+}
+
+static void read_remotes_file(struct remote *remote)
+{
+	FILE *f = fopen(git_path("remotes/%s", remote->name), "r");
+
+	if (!f)
+		return;
+	while (fgets(buffer, BUF_SIZE, f)) {
+		int value_list;
+		char *s, *p;
+
+		if (!prefixcmp(buffer, "URL:")) {
+			value_list = 0;
+			s = buffer + 4;
+		} else if (!prefixcmp(buffer, "Push:")) {
+			value_list = 1;
+			s = buffer + 5;
+		} else
+			continue;
+
+		while (isspace(*s))
+			s++;
+		if (!*s)
+			continue;
+
+		p = s + strlen(s);
+		while (isspace(p[-1]))
+			*--p = 0;
+
+		switch (value_list) {
+		case 0:
+			add_uri(remote, xstrdup(s));
+			break;
+		case 1:
+			add_push_refspec(remote, xstrdup(s));
+			break;
+		}
+	}
+}
+
+static void read_branches_file(struct remote *remote)
+{
+	const char *slash = strchr(remote->name, '/');
+	int n = slash ? slash - remote->name : 1000;
+	FILE *f = fopen(git_path("branches/%.*s", n, remote->name), "r");
+	char *s, *p;
+	int len;
+
+	if (!f)
+		return;
+	s = fgets(buffer, BUF_SIZE, f);
+	fclose(f);
+	if (!s)
+		return;
+	while (isspace(*s))
+		s++;
+	if (!*s)
+		return;
+	p = s + strlen(s);
+	while (isspace(p[-1]))
+		*--p = 0;
+	len = p - s;
+	if (slash)
+		len += strlen(slash);
+	p = xmalloc(len + 1);
+	strcpy(p, s);
+	if (slash)
+		strcat(p, slash);
+	add_uri(remote, p);
+}
+
+static char *default_remote_name = NULL;
+static const char *current_branch = NULL;
+static int current_branch_len = 0;
+
+static int handle_config(const char *key, const char *value)
+{
+	const char *name;
+	const char *subkey;
+	struct remote *remote;
+	if (!prefixcmp(key, "branch.") && current_branch &&
+	    !strncmp(key + 7, current_branch, current_branch_len) &&
+	    !strcmp(key + 7 + current_branch_len, ".remote")) {
+		free(default_remote_name);
+		default_remote_name = xstrdup(value);
+	}
+	if (prefixcmp(key,  "remote."))
+		return 0;
+	name = key + 7;
+	subkey = strrchr(name, '.');
+	if (!subkey)
+		return error("Config with no key for remote %s", name);
+	remote = make_remote(name, subkey - name);
+	if (!strcmp(subkey, ".url")) {
+		add_uri(remote, xstrdup(value));
+	} else if (!strcmp(subkey, ".push")) {
+		add_push_refspec(remote, xstrdup(value));
+	} else if (!strcmp(subkey, ".receivepack")) {
+		if (!remote->receivepack)
+			remote->receivepack = xstrdup(value);
+		else
+			error("more than one receivepack given, using the first");
+	}
+	return 0;
+}
+
+static void read_config(void)
+{
+	unsigned char sha1[20];
+	const char *head_ref;
+	int flag;
+	if (default_remote_name) // did this already
+		return;
+	default_remote_name = xstrdup("origin");
+	current_branch = NULL;
+	head_ref = resolve_ref("HEAD", sha1, 0, &flag);
+	if (head_ref && (flag & REF_ISSYMREF) &&
+	    !prefixcmp(head_ref, "refs/heads/")) {
+		current_branch = head_ref + strlen("refs/heads/");
+		current_branch_len = strlen(current_branch);
+	}
+	git_config(handle_config);
+}
+
+struct remote *remote_get(const char *name)
+{
+	struct remote *ret;
+
+	read_config();
+	if (!name)
+		name = default_remote_name;
+	ret = make_remote(name, 0);
+	if (name[0] != '/') {
+		if (!ret->uri)
+			read_remotes_file(ret);
+		if (!ret->uri)
+			read_branches_file(ret);
+	}
+	if (!ret->uri)
+		add_uri(ret, name);
+	if (!ret->uri)
+		return NULL;
+	return ret;
+}
diff --git a/remote.h b/remote.h
new file mode 100644
index 0000000..73747a8
--- /dev/null
+++ b/remote.h
@@ -0,0 +1,18 @@
+#ifndef REMOTE_H
+#define REMOTE_H
+
+struct remote {
+	const char *name;
+
+	const char **uri;
+	int uri_nr;
+
+	const char **push_refspec;
+	int push_refspec_nr;
+
+	const char *receivepack;
+};
+
+struct remote *remote_get(const char *name);
+
+#endif
-- 
1.5.2.rc2.45.g3d9b43-dirty

^ permalink raw reply related

* [PATCH 2/3] Move refspec parser from connect.c and cache.h to remote.{c,h}
From: Daniel Barkalow @ 2007-05-12  2:39 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
---
 cache.h     |    2 -
 connect.c   |  240 +---------------------------------------------------------
 http-push.c |    1 +
 remote.c    |  246 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 remote.h    |   12 +++
 send-pack.c |    1 +
 6 files changed, 261 insertions(+), 241 deletions(-)

diff --git a/cache.h b/cache.h
index 8e76152..46057f8 100644
--- a/cache.h
+++ b/cache.h
@@ -465,8 +465,6 @@ struct ref {
 extern pid_t git_connect(int fd[2], char *url, const char *prog);
 extern int finish_connect(pid_t pid);
 extern int path_match(const char *path, int nr, char **match);
-extern int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
-		      int nr_refspec, char **refspec, int all);
 extern int get_ack(int fd, unsigned char *result_sha1);
 extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags);
 extern int server_supports(const char *feature);
diff --git a/connect.c b/connect.c
index da89c9c..50ec559 100644
--- a/connect.c
+++ b/connect.c
@@ -4,6 +4,7 @@
 #include "quote.h"
 #include "refs.h"
 #include "run-command.h"
+#include "remote.h"
 
 static char *server_capabilities;
 
@@ -128,245 +129,6 @@ int path_match(const char *path, int nr, char **match)
 	return 0;
 }
 
-struct refspec {
-	char *src;
-	char *dst;
-	char force;
-};
-
-/*
- * A:B means fast forward remote B with local A.
- * +A:B means overwrite remote B with local A.
- * +A is a shorthand for +A:A.
- * A is a shorthand for A:A.
- * :B means delete remote B.
- */
-static struct refspec *parse_ref_spec(int nr_refspec, char **refspec)
-{
-	int i;
-	struct refspec *rs = xcalloc(sizeof(*rs), (nr_refspec + 1));
-	for (i = 0; i < nr_refspec; i++) {
-		char *sp, *dp, *ep;
-		sp = refspec[i];
-		if (*sp == '+') {
-			rs[i].force = 1;
-			sp++;
-		}
-		ep = strchr(sp, ':');
-		if (ep) {
-			dp = ep + 1;
-			*ep = 0;
-		}
-		else
-			dp = sp;
-		rs[i].src = sp;
-		rs[i].dst = dp;
-	}
-	rs[nr_refspec].src = rs[nr_refspec].dst = NULL;
-	return rs;
-}
-
-static int count_refspec_match(const char *pattern,
-			       struct ref *refs,
-			       struct ref **matched_ref)
-{
-	int patlen = strlen(pattern);
-	struct ref *matched_weak = NULL;
-	struct ref *matched = NULL;
-	int weak_match = 0;
-	int match = 0;
-
-	for (weak_match = match = 0; refs; refs = refs->next) {
-		char *name = refs->name;
-		int namelen = strlen(name);
-		int weak_match;
-
-		if (namelen < patlen ||
-		    memcmp(name + namelen - patlen, pattern, patlen))
-			continue;
-		if (namelen != patlen && name[namelen - patlen - 1] != '/')
-			continue;
-
-		/* A match is "weak" if it is with refs outside
-		 * heads or tags, and did not specify the pattern
-		 * in full (e.g. "refs/remotes/origin/master") or at
-		 * least from the toplevel (e.g. "remotes/origin/master");
-		 * otherwise "git push $URL master" would result in
-		 * ambiguity between remotes/origin/master and heads/master
-		 * at the remote site.
-		 */
-		if (namelen != patlen &&
-		    patlen != namelen - 5 &&
-		    prefixcmp(name, "refs/heads/") &&
-		    prefixcmp(name, "refs/tags/")) {
-			/* We want to catch the case where only weak
-			 * matches are found and there are multiple
-			 * matches, and where more than one strong
-			 * matches are found, as ambiguous.  One
-			 * strong match with zero or more weak matches
-			 * are acceptable as a unique match.
-			 */
-			matched_weak = refs;
-			weak_match++;
-		}
-		else {
-			matched = refs;
-			match++;
-		}
-	}
-	if (!matched) {
-		*matched_ref = matched_weak;
-		return weak_match;
-	}
-	else {
-		*matched_ref = matched;
-		return match;
-	}
-}
-
-static void link_dst_tail(struct ref *ref, struct ref ***tail)
-{
-	**tail = ref;
-	*tail = &ref->next;
-	**tail = NULL;
-}
-
-static struct ref *try_explicit_object_name(const char *name)
-{
-	unsigned char sha1[20];
-	struct ref *ref;
-	int len;
-
-	if (!*name) {
-		ref = xcalloc(1, sizeof(*ref) + 20);
-		strcpy(ref->name, "(delete)");
-		hashclr(ref->new_sha1);
-		return ref;
-	}
-	if (get_sha1(name, sha1))
-		return NULL;
-	len = strlen(name) + 1;
-	ref = xcalloc(1, sizeof(*ref) + len);
-	memcpy(ref->name, name, len);
-	hashcpy(ref->new_sha1, sha1);
-	return ref;
-}
-
-static int match_explicit_refs(struct ref *src, struct ref *dst,
-			       struct ref ***dst_tail, struct refspec *rs)
-{
-	int i, errs;
-	for (i = errs = 0; rs[i].src; i++) {
-		struct ref *matched_src, *matched_dst;
-
-		matched_src = matched_dst = NULL;
-		switch (count_refspec_match(rs[i].src, src, &matched_src)) {
-		case 1:
-			break;
-		case 0:
-			/* The source could be in the get_sha1() format
-			 * not a reference name.  :refs/other is a
-			 * way to delete 'other' ref at the remote end.
-			 */
-			matched_src = try_explicit_object_name(rs[i].src);
-			if (matched_src)
-				break;
-			errs = 1;
-			error("src refspec %s does not match any.",
-			      rs[i].src);
-			break;
-		default:
-			errs = 1;
-			error("src refspec %s matches more than one.",
-			      rs[i].src);
-			break;
-		}
-		switch (count_refspec_match(rs[i].dst, dst, &matched_dst)) {
-		case 1:
-			break;
-		case 0:
-			if (!memcmp(rs[i].dst, "refs/", 5)) {
-				int len = strlen(rs[i].dst) + 1;
-				matched_dst = xcalloc(1, sizeof(*dst) + len);
-				memcpy(matched_dst->name, rs[i].dst, len);
-				link_dst_tail(matched_dst, dst_tail);
-			}
-			else if (!strcmp(rs[i].src, rs[i].dst) &&
-				 matched_src) {
-				/* pushing "master:master" when
-				 * remote does not have master yet.
-				 */
-				int len = strlen(matched_src->name) + 1;
-				matched_dst = xcalloc(1, sizeof(*dst) + len);
-				memcpy(matched_dst->name, matched_src->name,
-				       len);
-				link_dst_tail(matched_dst, dst_tail);
-			}
-			else {
-				errs = 1;
-				error("dst refspec %s does not match any "
-				      "existing ref on the remote and does "
-				      "not start with refs/.", rs[i].dst);
-			}
-			break;
-		default:
-			errs = 1;
-			error("dst refspec %s matches more than one.",
-			      rs[i].dst);
-			break;
-		}
-		if (errs)
-			continue;
-		if (matched_dst->peer_ref) {
-			errs = 1;
-			error("dst ref %s receives from more than one src.",
-			      matched_dst->name);
-		}
-		else {
-			matched_dst->peer_ref = matched_src;
-			matched_dst->force = rs[i].force;
-		}
-	}
-	return -errs;
-}
-
-static struct ref *find_ref_by_name(struct ref *list, const char *name)
-{
-	for ( ; list; list = list->next)
-		if (!strcmp(list->name, name))
-			return list;
-	return NULL;
-}
-
-int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
-	       int nr_refspec, char **refspec, int all)
-{
-	struct refspec *rs = parse_ref_spec(nr_refspec, refspec);
-
-	if (nr_refspec)
-		return match_explicit_refs(src, dst, dst_tail, rs);
-
-	/* pick the remainder */
-	for ( ; src; src = src->next) {
-		struct ref *dst_peer;
-		if (src->peer_ref)
-			continue;
-		dst_peer = find_ref_by_name(dst, src->name);
-		if ((dst_peer && dst_peer->peer_ref) || (!dst_peer && !all))
-			continue;
-		if (!dst_peer) {
-			/* Create a new one and link it */
-			int len = strlen(src->name) + 1;
-			dst_peer = xcalloc(1, sizeof(*dst_peer) + len);
-			memcpy(dst_peer->name, src->name, len);
-			hashcpy(dst_peer->new_sha1, src->new_sha1);
-			link_dst_tail(dst_peer, dst_tail);
-		}
-		dst_peer->peer_ref = src;
-	}
-	return 0;
-}
-
 enum protocol {
 	PROTO_LOCAL = 1,
 	PROTO_SSH,
diff --git a/http-push.c b/http-push.c
index e3f7675..79d2c38 100644
--- a/http-push.c
+++ b/http-push.c
@@ -9,6 +9,7 @@
 #include "diff.h"
 #include "revision.h"
 #include "exec_cmd.h"
+#include "remote.h"
 
 #include <expat.h>
 
diff --git a/remote.c b/remote.c
index 1dd2e77..2ac7bc8 100644
--- a/remote.c
+++ b/remote.c
@@ -181,6 +181,44 @@ static void read_config(void)
 	git_config(handle_config);
 }
 
+static struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
+{
+	int i;
+	struct refspec *rs = xcalloc(sizeof(*rs), nr_refspec);
+	for (i = 0; i < nr_refspec; i++) {
+		const char *sp, *ep, *gp;
+		sp = refspec[i];
+		if (*sp == '+') {
+			rs[i].force = 1;
+			sp++;
+		}
+		gp = strchr(sp, '*');
+		ep = strchr(sp, ':');
+		if (gp && ep && gp > ep)
+			gp = NULL;
+		if (ep) {
+			if (ep[1]) {
+				const char *glob = strchr(ep + 1, '*');
+				if (!glob)
+					gp = NULL;
+				if (gp)
+					rs[i].dest = xstrndup(ep + 1,
+							      glob - ep - 1);
+				else
+					rs[i].dest = xstrdup(ep + 1);
+			}
+		} else {
+			ep = sp + strlen(sp);
+		}
+		if (gp) {
+			rs[i].pattern = 1;
+			ep = gp;
+		}
+		rs[i].src = xstrndup(sp, ep - sp);
+	}
+	return rs;
+}
+
 struct remote *remote_get(const char *name)
 {
 	struct remote *ret;
@@ -199,5 +237,213 @@ struct remote *remote_get(const char *name)
 		add_uri(ret, name);
 	if (!ret->uri)
 		return NULL;
+	ret->push = parse_ref_spec(ret->push_refspec_nr, ret->push_refspec);
 	return ret;
 }
+
+static int count_refspec_match(const char *pattern,
+			       struct ref *refs,
+			       struct ref **matched_ref)
+{
+	int patlen = strlen(pattern);
+	struct ref *matched_weak = NULL;
+	struct ref *matched = NULL;
+	int weak_match = 0;
+	int match = 0;
+
+	for (weak_match = match = 0; refs; refs = refs->next) {
+		char *name = refs->name;
+		int namelen = strlen(name);
+		int weak_match;
+
+		if (namelen < patlen ||
+		    memcmp(name + namelen - patlen, pattern, patlen))
+			continue;
+		if (namelen != patlen && name[namelen - patlen - 1] != '/')
+			continue;
+
+		/* A match is "weak" if it is with refs outside
+		 * heads or tags, and did not specify the pattern
+		 * in full (e.g. "refs/remotes/origin/master") or at
+		 * least from the toplevel (e.g. "remotes/origin/master");
+		 * otherwise "git push $URL master" would result in
+		 * ambiguity between remotes/origin/master and heads/master
+		 * at the remote site.
+		 */
+		if (namelen != patlen &&
+		    patlen != namelen - 5 &&
+		    prefixcmp(name, "refs/heads/") &&
+		    prefixcmp(name, "refs/tags/")) {
+			/* We want to catch the case where only weak
+			 * matches are found and there are multiple
+			 * matches, and where more than one strong
+			 * matches are found, as ambiguous.  One
+			 * strong match with zero or more weak matches
+			 * are acceptable as a unique match.
+			 */
+			matched_weak = refs;
+			weak_match++;
+		}
+		else {
+			matched = refs;
+			match++;
+		}
+	}
+	if (!matched) {
+		*matched_ref = matched_weak;
+		return weak_match;
+	}
+	else {
+		*matched_ref = matched;
+		return match;
+	}
+}
+
+static void link_dst_tail(struct ref *ref, struct ref ***tail)
+{
+	**tail = ref;
+	*tail = &ref->next;
+	**tail = NULL;
+}
+
+static struct ref *try_explicit_object_name(const char *name)
+{
+	unsigned char sha1[20];
+	struct ref *ref;
+	int len;
+
+	if (!*name) {
+		ref = xcalloc(1, sizeof(*ref) + 20);
+		strcpy(ref->name, "(delete)");
+		hashclr(ref->new_sha1);
+		return ref;
+	}
+	if (get_sha1(name, sha1))
+		return NULL;
+	len = strlen(name) + 1;
+	ref = xcalloc(1, sizeof(*ref) + len);
+	memcpy(ref->name, name, len);
+	hashcpy(ref->new_sha1, sha1);
+	return ref;
+}
+
+static int match_explicit_refs(struct ref *src, struct ref *dst,
+			       struct ref ***dst_tail, struct refspec *rs,
+			       int rs_nr)
+{
+	int i, errs;
+	for (i = errs = 0; i < rs_nr; i++) {
+		struct ref *matched_src, *matched_dst;
+
+		const char *dest = rs[i].dest;
+		if (dest == NULL)
+			dest = rs[i].src;
+
+		matched_src = matched_dst = NULL;
+		switch (count_refspec_match(rs[i].src, src, &matched_src)) {
+		case 1:
+			break;
+		case 0:
+			/* The source could be in the get_sha1() format
+			 * not a reference name.  :refs/other is a
+			 * way to delete 'other' ref at the remote end.
+			 */
+			matched_src = try_explicit_object_name(rs[i].src);
+			if (matched_src)
+				break;
+			errs = 1;
+			error("src refspec %s does not match any.",
+			      rs[i].src);
+			break;
+		default:
+			errs = 1;
+			error("src refspec %s matches more than one.",
+			      rs[i].src);
+			break;
+		}
+		switch (count_refspec_match(dest, dst, &matched_dst)) {
+		case 1:
+			break;
+		case 0:
+			if (!memcmp(dest, "refs/", 5)) {
+				int len = strlen(dest) + 1;
+				matched_dst = xcalloc(1, sizeof(*dst) + len);
+				memcpy(matched_dst->name, dest, len);
+				link_dst_tail(matched_dst, dst_tail);
+			}
+			else if (!strcmp(rs[i].src, dest) &&
+				 matched_src) {
+				/* pushing "master:master" when
+				 * remote does not have master yet.
+				 */
+				int len = strlen(matched_src->name) + 1;
+				matched_dst = xcalloc(1, sizeof(*dst) + len);
+				memcpy(matched_dst->name, matched_src->name,
+				       len);
+				link_dst_tail(matched_dst, dst_tail);
+			}
+			else {
+				errs = 1;
+				error("dst refspec %s does not match any "
+				      "existing ref on the remote and does "
+				      "not start with refs/.", rs[i].dest);
+			}
+			break;
+		default:
+			errs = 1;
+			error("dst refspec %s matches more than one.",
+			      dest);
+			break;
+		}
+		if (errs)
+			continue;
+		if (matched_dst->peer_ref) {
+			errs = 1;
+			error("dst ref %s receives from more than one src.",
+			      matched_dst->name);
+		}
+		else {
+			matched_dst->peer_ref = matched_src;
+			matched_dst->force = rs[i].force;
+		}
+	}
+	return -errs;
+}
+
+static struct ref *find_ref_by_name(struct ref *list, const char *name)
+{
+	for ( ; list; list = list->next)
+		if (!strcmp(list->name, name))
+			return list;
+	return NULL;
+}
+
+int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
+	       int nr_refspec, char **refspec, int all)
+{
+	struct refspec *rs =
+		parse_ref_spec(nr_refspec, (const char **) refspec);
+
+	if (nr_refspec)
+		return match_explicit_refs(src, dst, dst_tail, rs, nr_refspec);
+
+	/* pick the remainder */
+	for ( ; src; src = src->next) {
+		struct ref *dst_peer;
+		if (src->peer_ref)
+			continue;
+		dst_peer = find_ref_by_name(dst, src->name);
+		if ((dst_peer && dst_peer->peer_ref) || (!dst_peer && !all))
+			continue;
+		if (!dst_peer) {
+			/* Create a new one and link it */
+			int len = strlen(src->name) + 1;
+			dst_peer = xcalloc(1, sizeof(*dst_peer) + len);
+			memcpy(dst_peer->name, src->name, len);
+			hashcpy(dst_peer->new_sha1, src->new_sha1);
+			link_dst_tail(dst_peer, dst_tail);
+		}
+		dst_peer->peer_ref = src;
+	}
+	return 0;
+}
diff --git a/remote.h b/remote.h
index 73747a8..79cedde 100644
--- a/remote.h
+++ b/remote.h
@@ -8,6 +8,7 @@ struct remote {
 	int uri_nr;
 
 	const char **push_refspec;
+	struct refspec *push;
 	int push_refspec_nr;
 
 	const char *receivepack;
@@ -15,4 +16,15 @@ struct remote {
 
 struct remote *remote_get(const char *name);
 
+struct refspec {
+	unsigned force : 1;
+	unsigned pattern : 1;
+
+	const char *src;
+	char *dest;
+};
+
+int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
+	       int nr_refspec, char **refspec, int all);
+
 #endif
diff --git a/send-pack.c b/send-pack.c
index d5b5162..6851043 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -4,6 +4,7 @@
 #include "refs.h"
 #include "pkt-line.h"
 #include "run-command.h"
+#include "remote.h"
 
 static const char send_pack_usage[] =
 "git-send-pack [--all] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
-- 
1.5.2.rc2.45.g3d9b43-dirty

^ permalink raw reply related

* [PATCH 3/3] Add handlers for fetch-side configuration of remotes.
From: Daniel Barkalow @ 2007-05-12  2:39 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

These follow the pattern of the push side configuration, but aren't
taken from anywhere else, because git-fetch is still in shell.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
---
 remote.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 remote.h |   10 ++++++++++
 2 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/remote.c b/remote.c
index 2ac7bc8..8070803 100644
--- a/remote.c
+++ b/remote.c
@@ -17,6 +17,15 @@ static void add_push_refspec(struct remote *remote, const char *ref)
 	remote->push_refspec_nr = nr;
 }
 
+static void add_fetch_refspec(struct remote *remote, const char *ref)
+{
+	int nr = remote->fetch_refspec_nr + 1;
+	remote->fetch_refspec =
+		xrealloc(remote->fetch_refspec, nr * sizeof(char *));
+	remote->fetch_refspec[nr-1] = ref;
+	remote->fetch_refspec_nr = nr;
+}
+
 static void add_uri(struct remote *remote, const char *uri)
 {
 	int nr = remote->uri_nr + 1;
@@ -74,6 +83,9 @@ static void read_remotes_file(struct remote *remote)
 		} else if (!prefixcmp(buffer, "Push:")) {
 			value_list = 1;
 			s = buffer + 5;
+		} else if (!prefixcmp(buffer, "Pull:")) {
+			value_list = 2;
+			s = buffer + 5;
 		} else
 			continue;
 
@@ -93,6 +105,9 @@ static void read_remotes_file(struct remote *remote)
 		case 1:
 			add_push_refspec(remote, xstrdup(s));
 			break;
+		case 2:
+			add_fetch_refspec(remote, xstrdup(s));
+			break;
 		}
 	}
 }
@@ -154,6 +169,8 @@ static int handle_config(const char *key, const char *value)
 		add_uri(remote, xstrdup(value));
 	} else if (!strcmp(subkey, ".push")) {
 		add_push_refspec(remote, xstrdup(value));
+	} else if (!strcmp(subkey, ".fetch")) {
+		add_fetch_refspec(remote, xstrdup(value));
 	} else if (!strcmp(subkey, ".receivepack")) {
 		if (!remote->receivepack)
 			remote->receivepack = xstrdup(value);
@@ -237,10 +254,52 @@ struct remote *remote_get(const char *name)
 		add_uri(ret, name);
 	if (!ret->uri)
 		return NULL;
+	ret->fetch = parse_ref_spec(ret->fetch_refspec_nr, ret->fetch_refspec);
 	ret->push = parse_ref_spec(ret->push_refspec_nr, ret->push_refspec);
 	return ret;
 }
 
+int remote_has_uri(struct remote *remote, const char *uri)
+{
+	int i;
+	for (i = 0; i < remote->uri_nr; i++) {
+		if (!strcmp(remote->uri[i], uri))
+			return 1;
+	}
+	return 0;
+}
+
+int remote_find_tracking(struct remote *remote, struct refspec *refspec)
+{
+	int i;
+	for (i = 0; i < remote->fetch_refspec_nr; i++) {
+		struct refspec *fetch = &remote->fetch[i];
+		if (!fetch->dest)
+			continue;
+		if (fetch->pattern) {
+			if (!prefixcmp(refspec->src, fetch->src)) {
+				refspec->dest =
+					xmalloc(strlen(fetch->dest) +
+						strlen(refspec->src) -
+						strlen(fetch->src) + 1);
+				strcpy(refspec->dest, fetch->dest);
+				strcpy(refspec->dest + strlen(fetch->dest),
+				       refspec->src + strlen(fetch->src));
+				refspec->force = fetch->force;
+				return 0;
+			}
+		} else {
+			if (!strcmp(refspec->src, fetch->src)) {
+				refspec->dest = xstrdup(fetch->dest);
+				refspec->force = fetch->force;
+				return 0;
+			}
+		}
+	}
+	refspec->dest = NULL;
+	return -1;
+}
+
 static int count_refspec_match(const char *pattern,
 			       struct ref *refs,
 			       struct ref **matched_ref)
diff --git a/remote.h b/remote.h
index 79cedde..3608119 100644
--- a/remote.h
+++ b/remote.h
@@ -11,11 +11,17 @@ struct remote {
 	struct refspec *push;
 	int push_refspec_nr;
 
+	const char **fetch_refspec;
+	struct refspec *fetch;
+	int fetch_refspec_nr;
+
 	const char *receivepack;
 };
 
 struct remote *remote_get(const char *name);
 
+int remote_has_uri(struct remote *remote, const char *uri);
+
 struct refspec {
 	unsigned force : 1;
 	unsigned pattern : 1;
@@ -27,4 +33,8 @@ struct refspec {
 int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
 	       int nr_refspec, char **refspec, int all);
 
+/** For the given remote, reads the refspec's src and sets the other fields.
+ **/
+int remote_find_tracking(struct remote *remote, struct refspec *refspec);
+
 #endif
-- 
1.5.2.rc2.45.g3d9b43-dirty

^ permalink raw reply related

* Re: GIT on MinGW problem
From: Han-Wen Nienhuys @ 2007-05-12  3:30 UTC (permalink / raw)
  To: Aaron Gray; +Cc: Git Mailing List
In-Reply-To: <1dbc01c79432$b4400a80$0200a8c0@AMD2500>

Aaron Gray escreveu:
> Hello,
> 
> I have installed the git-1.5.1-1.mingw.exe from
> http://lilypond.org/git/binaries/mingw/.
> 
> On typing 'git' I get a message box saying :-
> 
>        The procedure entry point libiconv could not be located in the
> dynamic link library libiconv-2.dll.
> 
> I cannot seem to find libiconv-2.dll anywhere either.

This should be fixed in 

http://lilypond.org/git/binaries/mingw/git-1.5.1-2.mingw.exe

it should also set $PATH.

-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen

^ permalink raw reply

* [PATCH] git-add: allow path limiting with -u
From: Jeff King @ 2007-05-12  6:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, jnareb, cworth

Rather than updating all working tree paths, we limit
ourselves to paths listed on the command line.

Signed-off-by: Jeff King <peff@peff.net>
---
This turned out to be quite easy to implement. Patch is slightly larger
than necessary due to removing _all_ from the variable names, but I
think that better expresses the new functionality.

I'm not sure that the documentation needs updated at all; I had just
assumed after reading it that 'git-add -u foo' would DWIM.

 builtin-add.c         |   13 ++++++-------
 t/t2200-add-update.sh |   38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 7 deletions(-)
 create mode 100755 t/t2200-add-update.sh

diff --git a/builtin-add.c b/builtin-add.c
index 5e6748f..1591171 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -16,7 +16,7 @@
 static const char builtin_add_usage[] =
 "git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--] <filepattern>...";
 
-static int take_all_worktree_changes;
+static int take_worktree_changes;
 static const char *excludes_file;
 
 static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
@@ -122,11 +122,12 @@ static void update_callback(struct diff_queue_struct *q,
 	}
 }
 
-static void update_all(int verbose)
+static void update(int verbose, const char **files)
 {
 	struct rev_info rev;
 	init_revisions(&rev, "");
 	setup_revisions(0, NULL, &rev, NULL);
+	rev.prune_data = get_pathspec(rev.prefix, files);
 	rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
 	rev.diffopt.format_callback = update_callback;
 	rev.diffopt.format_callback_data = &verbose;
@@ -200,16 +201,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 			continue;
 		}
 		if (!strcmp(arg, "-u")) {
-			take_all_worktree_changes = 1;
+			take_worktree_changes = 1;
 			continue;
 		}
 		usage(builtin_add_usage);
 	}
 
-	if (take_all_worktree_changes) {
-		if (i < argc)
-			die("-u and explicit paths are incompatible");
-		update_all(verbose);
+	if (take_worktree_changes) {
+		update(verbose, argv + i);
 		goto finish;
 	}
 
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
new file mode 100755
index 0000000..83005e7
--- /dev/null
+++ b/t/t2200-add-update.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+test_description='git-add -u with path limiting
+
+This test creates a working tree state with three files:
+
+  top (previously committed, modified)
+  dir/sub (previously committed, modified)
+  dir/other (untracked)
+
+and issues a git-add -u with path limiting on "dir" to add
+only the updates to dir/sub.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+echo initial >top &&
+mkdir dir &&
+echo initial >dir/sub &&
+git-add dir/sub top &&
+git-commit -m initial &&
+echo changed >top &&
+echo changed >dir/sub &&
+echo other >dir/other
+'
+
+test_expect_success 'update' 'git-add -u dir'
+
+test_expect_success 'update touched correct path' \
+  'test "`git-diff-files --name-status dir/sub`" = ""'
+
+test_expect_success 'update did not touch other tracked files' \
+  'test "`git-diff-files --name-status top`" = "M	top"'
+
+test_expect_success 'update did not touch untracked files' \
+  'test "`git-diff-files --name-status dir/other`" = ""'
+
+test_done
-- 
1.5.2.rc3.709.g07945-dirty

^ permalink raw reply related

* Re: [PATCH 0/3] Remotes library, take 3
From: Junio C Hamano @ 2007-05-12  7:10 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0705112234520.18541@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> This series is the same as the previous version, except that it matches 
> the current behavior of builtin-push with respect to treating names as 
> literal URIs.

Thanks.

        diff --git a/remote.c b/remote.c
        index 32a0acf..1dd2e77 100644
        --- a/remote.c
        +++ b/remote.c
        @@ -189,12 +189,14 @@ struct remote *remote_get(const char *name)
                if (!name)
                        name = default_remote_name;
                ret = make_remote(name, 0);
        -	if (*name == '/')
        -		add_uri(ret, name);
        -	if (!ret->uri)
        -		read_remotes_file(ret);
        +	if (name[0] != '/') {
        +		if (!ret->uri)
        +			read_remotes_file(ret);
        +		if (!ret->uri)
        +			read_branches_file(ret);
        +	}
                if (!ret->uri)
        -		read_branches_file(ret);
        +		add_uri(ret, name);
                if (!ret->uri)
                        return NULL;
                return ret;

This is more similar to the original from builtin-push.c than
your previous round, but it is still not identical.

The differences should not matter in real life, but I think we
need to make it clear what the differences are to warn users.
Here is my reading of the change (please correct me).

Earlier.

  - A name that does not begin with a slash could be a remote
    shorthand.  Check remotes, config and branches in this order
    and stop once a match is found.

  - Otherwise use the name as a literal URI.

This patch.

  - Config always wins.

  - A name that does not begin with a slash could be found in
    remotes or branches; check them in this order.

  - Otherwise use it as is.

Theoretically people _could_ have had a config like

	[remote "/pub"]
		url = blah

but it would never have matched.  This ``broken'' config file
suddenly start to interfere when somebody does:

	$ git push /pub

Also people may have had a remotes and config of the same name,
and currently what is defined in config is ignored, but with the
new code, config takes precedence.  Which is unarguably good,
but still a change I should remember to write down in the
release notes, hence prefer to have it clearly described in the
commit log message.

We probably would not care about the first difference, but it is
easy enough to guard against, I think.  Perhaps with this patch?

-- >8 --
parsing remotes: forbid "remote./foo.variable" and fix segfault

Historically we did not pay attention to a remote shorthand
defined in the config file whose name starts with a slash
(because we always took such a string as a literal localfile
URL), but the new organization of the parsing code makes config
always take precedence.  It does not make much sense to define
such a remote shorthand, so protect ourselves against it.

Also, the code forgot that a config variable could be spelled
without a value to denote a boolean set to true, in which case
the config parser passes a NULL in value parameter, and run
xstrdup() on it without checking.  Fix this.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 remote.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/remote.c b/remote.c
index 1dd2e77..05df196 100644
--- a/remote.c
+++ b/remote.c
@@ -149,7 +149,24 @@ static int handle_config(const char *key, const char *value)
 	subkey = strrchr(name, '.');
 	if (!subkey)
 		return error("Config with no key for remote %s", name);
+	if (*subkey == '/')
+		return error("Config remote shorthand cannot begin with '/': %s", name);
 	remote = make_remote(name, subkey - name);
+	if (!value) {
+		/* if we ever have a boolean variable, e.g. "remote.*.disabled"
+		 * [remote "frotz"]
+		 *	disabled
+		 * is a valid way to set it to true; we get NULL in value so
+		 * we need to handle it here.
+		 *
+		 * if (!strcmp(subkey, ".disabled")) {
+		 * 	val = git_config_bool(key, value);
+		 *	return 0;
+		 * } else
+		 *
+		 */
+		return error("Config with no value for remote %s", name);
+	}
 	if (!strcmp(subkey, ".url")) {
 		add_uri(remote, xstrdup(value));
 	} else if (!strcmp(subkey, ".push")) {

^ permalink raw reply related

* Re: Using StGIT for tweaking already-committed stuff
From: Yann Dirson @ 2007-05-12  7:10 UTC (permalink / raw)
  To: Petr Baudis, Carl Worth, J. Bruce Fields, Linus Torvalds,
	Johannes Sixt, catalin.marinas, git
In-Reply-To: <20070511224325.GA13310@diana.vm.bytemark.co.uk>

On Sat, May 12, 2007 at 12:43:25AM +0200, Karl Hasselström wrote:
> It's only unothodox if you expect git and stgit to not always mix so
> well. But if we have the ambition that they should interoperate as
> near to seamlessly as we can make them, this kind of workflow becomes
> very natural.

It is great that this is possible, but I'm not sure I'll ever see it
as "very natural" :)

> It shouldn't be necessary with a manual "assimilate" step. If stgit
> finds that there are unadorned git commits on top of the patch stack,
> it should do the assimilation automatically. With that in place, "stg
> new" and "stg refresh" would be nearly superfluous, since git-commit
> with and without --amend does the same thing -- the only thing they
> won't do is give the user the option of manually choosing the patch
> name.

Hm.  I'm not that convinced :)

Eg, imagine a merge commit somewhere in the stack.  What would stgit
do with that ?

> I believe this sort of integration is the way to go. It'll be
> beneficial for git users who want to occasionally use some stgit to
> rebase their patch series, since they'll not have to learn more than
> two or three new commands in addition to the git they already know.
> Heavy stgit users will benefit from having the much larger git
> community maintaining a large subset of the porcelain they use,
> instead of having to duplicate the effort and always lag behind.
> 
> This is no binary choice, of course. One could certainly imagine a
> compromise where stgit becomes much easier to mix with git than today,
> but still retains the current command set.

I quite like the idea of makeing it easier to mix them, and removing
the real duplicates from stgit, but I think that we should be careful
not to remove power from stgit while doing this.

Best regards,
-- 
Yann.

^ permalink raw reply

* Re: [PATCH] git-add: allow path limiting with -u
From: Junio C Hamano @ 2007-05-12  7:13 UTC (permalink / raw)
  To: Jeff King; +Cc: git, jnareb, cworth
In-Reply-To: <20070512064159.GA7471@coredump.intra.peff.net>

Jeff King <peff@peff.net> writes:

> Rather than updating all working tree paths, we limit
> ourselves to paths listed on the command line.
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> This turned out to be quite easy to implement. Patch is slightly larger
> than necessary due to removing _all_ from the variable names, but I
> think that better expresses the new functionality.
>
> I'm not sure that the documentation needs updated at all; I had just
> assumed after reading it that 'git-add -u foo' would DWIM.

Wonderful, and I agree it should be almost trivial once you
understand how diff works.  Will take a look.

^ permalink raw reply

* Re: [PATCH 0/3] Remotes library, take 3
From: Daniel Barkalow @ 2007-05-12  7:25 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7viray5xfj.fsf@assigned-by-dhcp.cox.net>

On Sat, 12 May 2007, Junio C Hamano wrote:

> Daniel Barkalow <barkalow@iabervon.org> writes:
> 
> > This series is the same as the previous version, except that it matches 
> > the current behavior of builtin-push with respect to treating names as 
> > literal URIs.
> 
> Thanks.
> 
>         diff --git a/remote.c b/remote.c
>         index 32a0acf..1dd2e77 100644
>         --- a/remote.c
>         +++ b/remote.c
>         @@ -189,12 +189,14 @@ struct remote *remote_get(const char *name)
>                 if (!name)
>                         name = default_remote_name;
>                 ret = make_remote(name, 0);
>         -	if (*name == '/')
>         -		add_uri(ret, name);
>         -	if (!ret->uri)
>         -		read_remotes_file(ret);
>         +	if (name[0] != '/') {
>         +		if (!ret->uri)
>         +			read_remotes_file(ret);
>         +		if (!ret->uri)
>         +			read_branches_file(ret);
>         +	}
>                 if (!ret->uri)
>         -		read_branches_file(ret);
>         +		add_uri(ret, name);
>                 if (!ret->uri)
>                         return NULL;
>                 return ret;
> 
> This is more similar to the original from builtin-push.c than
> your previous round, but it is still not identical.
> 
> The differences should not matter in real life, but I think we
> need to make it clear what the differences are to warn users.
> Here is my reading of the change (please correct me).
> 
> Earlier.
> 
>   - A name that does not begin with a slash could be a remote
>     shorthand.  Check remotes, config and branches in this order
>     and stop once a match is found.
> 
>   - Otherwise use the name as a literal URI.
> 
> This patch.
> 
>   - Config always wins.
> 
>   - A name that does not begin with a slash could be found in
>     remotes or branches; check them in this order.
> 
>   - Otherwise use it as is.
> 
> Theoretically people _could_ have had a config like
> 
> 	[remote "/pub"]
> 		url = blah
> 
> but it would never have matched.  This ``broken'' config file
> suddenly start to interfere when somebody does:
> 
> 	$ git push /pub

This is true, and I missed it before. Feel free to mention it in the 
appropriate commit message.

> Also people may have had a remotes and config of the same name,
> and currently what is defined in config is ignored, but with the
> new code, config takes precedence.  Which is unarguably good,
> but still a change I should remember to write down in the
> release notes, hence prefer to have it clearly described in the
> commit log message.

This is in the message for [1/3] already, along with the other change: it 
will use the current branch's remote, if there is one, instead of "origin" 
if no repository is given on the command line.

I was only claiming here (incorrectly, it turns out) that the configured 
remote vs. literal URI behavior is the same with this series.

> We probably would not care about the first difference, but it is
> easy enough to guard against, I think.  Perhaps with this patch?
> 
> -- >8 --
> diff --git a/remote.c b/remote.c
> index 1dd2e77..05df196 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -149,7 +149,24 @@ static int handle_config(const char *key, const char *value)
>  	subkey = strrchr(name, '.');
>  	if (!subkey)
>  		return error("Config with no key for remote %s", name);
> +	if (*subkey == '/')
> +		return error("Config remote shorthand cannot begin with '/': %s", name);

Maybe just return? If we change the behavior to give an error in this 
situation, we might as well make the config file actually take effect 
instead.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: [PATCH 2/3] Move refspec parser from connect.c and cache.h to remote.{c,h}
From: Junio C Hamano @ 2007-05-12  7:32 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0705112238420.18541@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> diff --git a/remote.c b/remote.c
> index 1dd2e77..2ac7bc8 100644
> --- a/remote.c
> +++ b/remote.c
> @@ -181,6 +181,44 @@ static void read_config(void)
> + ...
> +static int match_explicit_refs(struct ref *src, struct ref *dst,
> +			       struct ref ***dst_tail, struct refspec *rs,
> +			       int rs_nr)
> +{
> +	int i, errs;
> +	for (i = errs = 0; i < rs_nr; i++) {
> +		struct ref *matched_src, *matched_dst;
> +
> +		const char *dest = rs[i].dest;
> +		if (dest == NULL)
> +			dest = rs[i].src;

I am not a big fan of gratuitous renaming of structure members
and variables such as this s/dst/dest/, especially when the
change breaks consistency (between src vs dst -- you left
matched_dst intact).

> ...
> +		switch (count_refspec_match(dest, dst, &matched_dst)) {
> ...
> +		case 0:
> +			if (!memcmp(dest, "refs/", 5)) {
> ...
> +			else {
> +				errs = 1;
> +				error("dst refspec %s does not match any "
> +				      "existing ref on the remote and does "
> +				      "not start with refs/.", rs[i].dest);
> +			}

I think you meant to say 'dest' instead of 'rs[i].dest' here.

> +...
> +	}
> +	return -errs;
> +}

^ permalink raw reply

* Re: [PATCH] Allow fetching references from any namespace
From: Alex Riesen @ 2007-05-12  7:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vlkfv9j3c.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano, Fri, May 11, 2007 22:54:47 +0200:
> Alex Riesen <raa.lkml@gmail.com> writes:
> 
> > not only from the three defined: heads, tags and remotes.
> >
> > Noticed when I tried to fetch the references created by git-p4-import.bat:
> > they are placed into separate namespace (refs/p4import/, to avoid showing
> > them in git-branch output). As canon_refs_list_for_fetch always prepended
> > refs/heads/ it was impossible, and annoying: it worked before. Normally,
> > the p4import references are useless anywhere but in the directory managed
> > by perforce, but in this special case the cloned directory was supposed
> > to be a backup, including the p4import branch: it keeps information about
> > where the imported perforce state came from.
> 
> Have no objection to the patch itself, but mind pointing out
> where we broke it (I suspect it is around 1.5.0)?
> 

Maybe even much earlier. According to

    git log -p --decorate -- git-fetch-script git-parse-remote-script

    commit ac4b0cff00b7629657e61a1d6e1f1a1250d03198
    Author: Junio C Hamano <junkio@cox.net>
    Date:   Sat Aug 20 02:52:24 2005 -0700

	[PATCH] Start adding the $GIT_DIR/remotes/ support.

    +canon_refs_list_for_fetch () {
    +       for ref
    +       do
    +               expr "$ref" : '.*:' >/dev/null || ref="${ref}:"
    +               remote=$(expr "$ref" : '\([^:]*\):')
    +               local=$(expr "$ref" : '[^:]*:\(.*\)')
    +               case "$remote" in
    +               '') remote=HEAD ;;
    +               *) remote="refs/heads/$remote" ;;
    +               esac
    +               case "$local" in
    +               '') local= ;;
    +               *) local="refs/heads/$local" ;;
    +               esac
    +               echo "${remote}:${local}"
    +       done
    +}

it was this way since at least Aug 2005.

^ permalink raw reply

* Re: [PATCH 1/3] Move remote parsing into a library file out of builtin-push.
From: Junio C Hamano @ 2007-05-12  7:51 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0705112238260.18541@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> The new parser is different from the one in builtin-push in two ways:
> the default is to use the current branch's remote, if there is one,
> before "origin"; and config is used in preference to remotes.

Please chuck my comment about describing differences in the
previous message---you did it already.  Sorry.

> diff --git a/remote.c b/remote.c
> new file mode 100644
> index 0000000..1dd2e77
> --- /dev/null
> +++ b/remote.c
> @@ -0,0 +1,203 @@
> +#include "cache.h"
> +#include "remote.h"
> +#include "refs.h"
> +
> +static struct remote **remotes;
> +static int allocated_remotes;
> +
> +#define BUF_SIZE (2084)
> +static char buffer[BUF_SIZE];

Heh, inherited a funny constant from the original...  I guess
most likely he meant 2048 ;-).

> +static void read_remotes_file(struct remote *remote)
> +{
> +	FILE *f = fopen(git_path("remotes/%s", remote->name), "r");
> +
> +	if (!f)
> +		return;
> +	while (fgets(buffer, BUF_SIZE, f)) {
> +...
> +	}
> +}

I sense a slight "FILE *" leak here...

^ permalink raw reply

* Re: [PATCH] Allow fetching references from any namespace
From: Junio C Hamano @ 2007-05-12  7:55 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git
In-Reply-To: <20070512074049.GA2410@steel.home>

Alex Riesen <raa.lkml@gmail.com> writes:

> Junio C Hamano, Fri, May 11, 2007 22:54:47 +0200:
>> Alex Riesen <raa.lkml@gmail.com> writes:
>> 
>> > not only from the three defined: heads, tags and remotes.
>> >
>> > Noticed when I tried to fetch the references created by git-p4-import.bat:
>> > they are placed into separate namespace (refs/p4import/, to avoid showing
>> > them in git-branch output). As canon_refs_list_for_fetch always prepended
>> > refs/heads/ it was impossible, and annoying: it worked before. Normally,
>> > the p4import references are useless anywhere but in the directory managed
>> > by perforce, but in this special case the cloned directory was supposed
>> > to be a backup, including the p4import branch: it keeps information about
>> > where the imported perforce state came from.
>> 
>> Have no objection to the patch itself, but mind pointing out
>> where we broke it (I suspect it is around 1.5.0)?
>> 
>
> Maybe even much earlier. According to
>
>     git log -p --decorate -- git-fetch-script git-parse-remote-script
>
>     commit ac4b0cff00b7629657e61a1d6e1f1a1250d03198
>     Author: Junio C Hamano <junkio@cox.net>
>     Date:   Sat Aug 20 02:52:24 2005 -0700
>
> 	[PATCH] Start adding the $GIT_DIR/remotes/ support.

Sounds like it is not even a regression but just was not
supposed to work from the beginning.

Not that I think lifting that restriction is a bad idea,
though.

^ permalink raw reply

* Re: Subproject clones
From: Sven Verdoolaege @ 2007-05-12  8:05 UTC (permalink / raw)
  To: Amos Waterland; +Cc: git
In-Reply-To: <20070512011600.GA24354@us.ibm.com>

On Fri, May 11, 2007 at 09:16:00PM -0400, Amos Waterland wrote:
> In other words, given this:
> 
>  superproject
>   sub1
>    Makefile
>   sub2
>    Makefile
> 
> when somebody does `git-clone superproject', I believe they expect to
> get the same tree.  Instead, they get this:

I'm working on something like that.
See the thread at

	http://article.gmane.org/gmane.comp.version-control.git/46163

I hope to send out an updated version later this weekend.

skimo

^ permalink raw reply

* Transactions for git (and stgit) ?
From: Yann Dirson @ 2007-05-12  9:53 UTC (permalink / raw)
  To: Carl Worth; +Cc: Linus Torvalds, Johannes Sixt, git
In-Reply-To: <87wszg39cp.wl%cworth@cworth.org>

On Thu, May 10, 2007 at 09:57:10AM -0700, Carl Worth wrote:
> What I find myself wanting to type is just:
> 
> 	git cherry-pick A..B
> 
> But there is the whole problem of how to deal with any conflict that
> appears during the process.

Indeed this is a problem we also have in StGIT, when pushing multiple
patches after rebasing.  Currently we have to deal with the conflict
and forge a new command-line to finish the job, which is quite awkward.

In this respect, the --continue/--skip/--abort set of flags that
git-rebase has are really useful.

In fact, I have plans to deal with such behaviours with stgit
transactions: in this case, we have the need of user interaction in
the middle of a transaction, and the rebase flags mentionned above are
just a way for the user of continuing or aborting the transaction.

However, currently I'm not sure that git-rebase would be very robust
if the user would mess with HEAD before issuing one of these commands.
Maybe git would also benefit from a generic transaction mechanism of
some sort, so "cherry-pick A..B" and possibly others can behave in a
consistent way with rebase ?

It could even be more sensible to implement transactions at the git
level rather than at the stgit one...

Best regards,
-- 
Yann.

^ permalink raw reply

* [PATCH] Fix an unmatched comment end in arm/sha1_arm.S
From: Marco Costalba @ 2007-05-12 10:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
---
 arm/sha1_arm.S |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arm/sha1_arm.S b/arm/sha1_arm.S
index da92d20..a328b73 100644
--- a/arm/sha1_arm.S
+++ b/arm/sha1_arm.S
@@ -23,7 +23,7 @@ sha_transform:
 	stmfd	sp!, {r4 - r8, lr}

 	@ for (i = 0; i < 16; i++)
-	@         W[i] = ntohl(((uint32_t *)data)[i]); */
+	@         W[i] = ntohl(((uint32_t *)data)[i]);

 #ifdef __ARMEB__
 	mov	r4, r0
-- 
1.5.2.rc3

^ permalink raw reply related

* Re: Transactions for git (and stgit) ?
From: Karl Hasselström @ 2007-05-12 10:49 UTC (permalink / raw)
  To: Yann Dirson; +Cc: Carl Worth, Linus Torvalds, Johannes Sixt, git
In-Reply-To: <20070512095312.GK19253@nan92-1-81-57-214-146.fbx.proxad.net>

On 2007-05-12 11:53:12 +0200, Yann Dirson wrote:

> It could even be more sensible to implement transactions at the git
> level rather than at the stgit one...

Yes, please. (Unless a convincing technical argument pops up against
it, of course.) Any stgit invariant that isn't based on a git
invariant is one more thing that can break when git and stgit commands
are mixed.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle

^ permalink raw reply


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