Git development
 help / color / mirror / Atom feed
* [PATCH 2/5] Change order of -m option to update-ref.
From: Shawn Pearce @ 2006-05-19  9:15 UTC (permalink / raw)
  To: Junio Hamano; +Cc: git

The actual position doesn't matter but most people prefer to see
options appear before the arguments.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

---

 Documentation/git-update-ref.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

75d5d46e9d911ab657af3c2eef9b585ac6a36b18
diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index dfbd886..e062030 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -7,7 +7,7 @@ git-update-ref - update the object name 
 
 SYNOPSIS
 --------
-'git-update-ref' <ref> <newvalue> [<oldvalue>] [-m <reason>]
+'git-update-ref' [-m <reason>] <ref> <newvalue> [<oldvalue>]
 
 DESCRIPTION
 -----------
-- 
1.3.2.g7278

^ permalink raw reply related

* [PATCH 1/5] Correct force_write bug in refs.c
From: Shawn Pearce @ 2006-05-19  9:15 UTC (permalink / raw)
  To: Junio Hamano; +Cc: git

My earlier attempt at forcing a write for non-existant refs worked;
it forced a write for pretty much all refs.  This corrects the
condition to only force a write for refs which don't exist yet.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

---

 refs.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

5ee16115982c52fa9b8fa15c14b234608a8b935d
diff --git a/refs.c b/refs.c
index d3ddc82..eeb1196 100644
--- a/refs.c
+++ b/refs.c
@@ -305,7 +305,7 @@ static struct ref_lock* lock_ref_sha1_ba
 	lock->ref_file = strdup(path);
 	lock->lock_file = strdup(mkpath("%s.lock", lock->ref_file));
 	lock->log_file = strdup(git_path("logs/%s", lock->ref_file + plen));
-	lock->force_write = !lstat(lock->ref_file, &st) || errno == ENOENT;
+	lock->force_write = lstat(lock->ref_file, &st) && errno == ENOENT;
 
 	if (safe_create_leading_directories(lock->lock_file))
 		die("unable to create directory for %s", lock->lock_file);
-- 
1.3.2.g7278

^ permalink raw reply related

* [PATCH 0/5] More ref logging
From: Shawn Pearce @ 2006-05-19  9:14 UTC (permalink / raw)
  To: Junio Hamano; +Cc: git

These are on top of the other five I just sent:

* [PATCH 1/5] Correct force_write bug in refs.c

	Yea there was a bug in the last bug fix.  Now we
	really don't write the ref unless we need to.

* [PATCH 2/5] Change order of -m option to update-ref.

	Minor documentation nit noticed by Junio.

* [PATCH 3/5] Include ref log detail in commit, reset, etc.

	Enhance some core tools to use the new '-m' switch with
	update-ref.  Trivial but requires the new update-ref.

* [PATCH 4/5] Create/delete branch ref logs.

	This was discussed on #git earlier this morning.
	Automatically create the ref log if -l is given when creating
	a branch and delete the log when deleting the branch.

* [PATCH 5/5] Enable ref log creation in git checkout -b.

	Fix git checkout -b to behave like git branch.

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH 4/5] Log ref updates made by fetch.
From: Shawn Pearce @ 2006-05-19  8:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vodxuih2d.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> wrote:
> Shawn Pearce <spearce@spearce.org> writes:
> 
> > diff --git a/refs.c b/refs.c
> > index 31cf276..d3ddc82 100644
> > --- a/refs.c
> > +++ b/refs.c
> > @@ -142,6 +142,8 @@ static int do_for_each_ref(const char *b
> >  			namelen = strlen(de->d_name);
> >  			if (namelen > 255)
> >  				continue;
> > +			if (namelen>5 && !strcmp(de->d_name+namelen-5,".lock"))
> > +				continue;
> >  			memcpy(path + baselen, de->d_name, namelen+1);
> >  			if (stat(git_path("%s", path), &st) < 0)
> >  				continue;
> 
> Now this got me worried.  Until now I did not realize that we
> are clobbering refnames that ends with ".lock" if another ref
> with the name without ".locK" is updated.  Because we do not
> forbid a name that ends with ".lock" to be used as a refname,
> this is an accident waiting to happen.
> 
> Not your fault, though.  It was like this ever since the initial
> version of refs.c was accepted by Linus.
> 
> We could do one of two things: officially forbid any refname
> that ends with ".lock", or fix the lockfile naming convention.
> 
> Nobody should be relying on what the actual lockfile-to-be-
> renamed-to-become-the-real-file is called.  I suspect we would
> want to fix refs.c::ref_lock_file_name() to use a name that
> would never be used as a refname.
> 
> We could make it begin with ".", so the lock file for the master
> ".git/refs/heads/master" would become ".git/refs/heads/.master",
> for example.  That way, we cannot clobber a valid unrelated ref
> (".master" is not a valid ref name), and as an added bonus, you
> do not even have to have the above hunk.

Not a bad idea.  I found this bug because fetch.c was trying to
work on the bob.lock while it was fetching "heads/bob".  Which
didn't make sense to me, so I put this skip thing in...

I'd want to get all of the "lockers" move to using the common
lock code before changing the lock name to ".master" (for example)
but yes that's a good idea.

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH 4/5] Log ref updates made by fetch.
From: Junio C Hamano @ 2006-05-19  7:56 UTC (permalink / raw)
  To: Shawn Pearce; +Cc: git
In-Reply-To: <20060519072926.GE22257@spearce.org>

Shawn Pearce <spearce@spearce.org> writes:

> diff --git a/refs.c b/refs.c
> index 31cf276..d3ddc82 100644
> --- a/refs.c
> +++ b/refs.c
> @@ -142,6 +142,8 @@ static int do_for_each_ref(const char *b
>  			namelen = strlen(de->d_name);
>  			if (namelen > 255)
>  				continue;
> +			if (namelen>5 && !strcmp(de->d_name+namelen-5,".lock"))
> +				continue;
>  			memcpy(path + baselen, de->d_name, namelen+1);
>  			if (stat(git_path("%s", path), &st) < 0)
>  				continue;

Now this got me worried.  Until now I did not realize that we
are clobbering refnames that ends with ".lock" if another ref
with the name without ".locK" is updated.  Because we do not
forbid a name that ends with ".lock" to be used as a refname,
this is an accident waiting to happen.

Not your fault, though.  It was like this ever since the initial
version of refs.c was accepted by Linus.

We could do one of two things: officially forbid any refname
that ends with ".lock", or fix the lockfile naming convention.

Nobody should be relying on what the actual lockfile-to-be-
renamed-to-become-the-real-file is called.  I suspect we would
want to fix refs.c::ref_lock_file_name() to use a name that
would never be used as a refname.

We could make it begin with ".", so the lock file for the master
".git/refs/heads/master" would become ".git/refs/heads/.master",
for example.  That way, we cannot clobber a valid unrelated ref
(".master" is not a valid ref name), and as an added bonus, you
do not even have to have the above hunk.

Hmm?

^ permalink raw reply

* Re: [RFD] Git glossary: 'branch' and 'head' description
From: David Kågedal @ 2006-05-19  6:53 UTC (permalink / raw)
  To: git
In-Reply-To: <e4f1ta$e07$1@sea.gmane.org>

Jakub Narebski <jnareb@gmail.com> writes:

> In #git channel somebody asked about 'branches' and 'heads' and was referred
> to the glossary. I had taken then a look at appropriate glossary entries.
>
> In 'Documentation/glossary.txt' we have:
> ----  
> branch::
>         A non-cyclical graph of revisions, i.e. the complete history of
>         a particular revision, which is called the branch head. The
>         branch heads are stored in `$GIT_DIR/refs/heads/`.

[...]

> It is just me or the glossary entry for `branch` is unnecessary 
> complicated? 
>
> Let's take a look at other definitions:
>
>   In software engineering, 'branch' is a separate line of development, which 
>   among others allows development on a project to diverge in two directions, 
>   such as a stable and a development version. (WikiPedia:Branch)
>
>   In the CVS team development environment, a separate line of development 
>   where changes can be isolated. When a programmer changes files on 
>   a branch, those changes do not appear on the main trunk 
>   or other branches. (cvs.info)
>
> So from the user's point of view, 'branch' is simply _named line of
> development_. Refer to topic and tracking branches.

But the definition of 'branch' in git is quite different from the
definition in CVS or many other systems.  It CVS, each revision
(commit) belongs to a branch, and the branch is a linear sequence of
revisions, not a full DAG.  In git, a commit doesn't really "belong"
in any specific branch.

So, while it makes sense to describe branches as "lines of
development" in general terms, it is also important to note the
specific meaning of 'branch' in the context of git; i.e. as the
history of a single head commit.

I noticed that some of this seems to be changing slightly with the
introduction of branch logs, but I don't know how those are supposed
to be used yet.

-- 
David Kågedal

^ permalink raw reply

* [PATCH 5/5] Change 'master@noon' syntax to 'master@{noon}'.
From: Shawn Pearce @ 2006-05-19  7:29 UTC (permalink / raw)
  To: Junio Hamano; +Cc: git

Its ambiguous to parse "master@2006-05-17 18:30:foo" when foo is
meant as a file name and ":30" is meant as 30 minutes past 6 pm.
Therefore all date specifications in a sha1 expression must now
appear within brackets and the ':' splitter used for the path name
in a sha1 expression ignores ':' appearing within brackets.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

---

 Documentation/git-rev-parse.txt |   11 ++++----
 sha1_name.c                     |   27 ++++++++++++-------
 t/t1400-update-ref.sh           |   55 ++++++++++++++++++++++++++++-----------
 3 files changed, 62 insertions(+), 31 deletions(-)

eea4ae092b92129ef09e9caf6f6f2b523cd193cb
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index df308c3..b894694 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -124,11 +124,12 @@ syntax.
   happen to have both heads/master and tags/master, you can
   explicitly say 'heads/master' to tell git which one you mean.
 
-* A suffix '@' followed by a date specification such as 'yesterday'
-  (24 hours ago) or '1 month 2 weeks 3 days 1 hour 1 second ago'
-  to specify the value of the ref at a prior point in time.
-  This suffix may only be used immediately following a ref name
-  and the ref must have an existing log ($GIT_DIR/logs/<ref>).
+* A suffix '@' followed by a date specification enclosed in a brace
+  pair (e.g. '\{yesterday\}', '\{1 month 2 weeks 3 days 1 hour 1
+  second ago\}' or '\{1979-02-26 18:30:00\}') to specify the value
+  of the ref at a prior point in time.  This suffix may only be
+  used immediately following a ref name and the ref must have an
+  existing log ($GIT_DIR/logs/<ref>).
 
 * A suffix '{caret}' to a revision parameter means the first parent of
   that commit object.  '{caret}<n>' means the <n>th parent (i.e.
diff --git a/sha1_name.c b/sha1_name.c
index 4376cb3..fbbde1c 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -249,7 +249,7 @@ static int get_sha1_basic(const char *st
 	static const char *warning = "warning: refname '%.*s' is ambiguous.\n";
 	const char **p, *pathname;
 	char *real_path = NULL;
-	int refs_found = 0, at_mark;
+	int refs_found = 0, am;
 	unsigned long at_time = (unsigned long)-1;
 	unsigned char *this_result;
 	unsigned char sha1_from_ref[20];
@@ -257,16 +257,16 @@ static int get_sha1_basic(const char *st
 	if (len == 40 && !get_sha1_hex(str, sha1))
 		return 0;
 
-	/* At a given period of time? "@2 hours ago" */
-	for (at_mark = 1; at_mark < len; at_mark++) {
-		if (str[at_mark] == '@') {
-			int date_len = len - at_mark - 1;
+	/* At a given period of time? "@{2 hours ago}" */
+	for (am = 1; am < len - 1; am++) {
+		if (str[am] == '@' && str[am+1] == '{' && str[len-1] == '}') {
+			int date_len = len - am - 3;
 			char *date_spec = xmalloc(date_len + 1);
-			strncpy(date_spec, str + at_mark + 1, date_len);
+			strncpy(date_spec, str + am + 2, date_len);
 			date_spec[date_len] = 0;
 			at_time = approxidate(date_spec);
 			free(date_spec);
-			len = at_mark;
+			len = am;
 			break;
 		}
 	}
@@ -482,7 +482,7 @@ static int get_sha1_1(const char *name, 
  */
 int get_sha1(const char *name, unsigned char *sha1)
 {
-	int ret;
+	int ret, bracket_depth;
 	unsigned unused;
 	int namelen = strlen(name);
 	const char *cp;
@@ -528,8 +528,15 @@ int get_sha1(const char *name, unsigned 
 		}
 		return -1;
 	}
-	cp = strchr(name, ':');
-	if (cp) {
+	for (cp = name, bracket_depth = 0; *cp; cp++) {
+		if (*cp == '{')
+			bracket_depth++;
+		else if (bracket_depth && *cp == '}')
+			bracket_depth--;
+		else if (!bracket_depth && *cp == ':')
+			break;
+	}
+	if (*cp == ':') {
 		unsigned char tree_sha1[20];
 		if (!get_sha1_1(name, cp-name, tree_sha1))
 			return get_tree_entry(tree_sha1, cp+1, sha1,
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 7858d86..f6b076b 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -125,52 +125,75 @@ ed="Thu, 26 May 2005 18:32:00 -0500"
 gd="Thu, 26 May 2005 18:33:00 -0500"
 ld="Thu, 26 May 2005 18:43:00 -0500"
 test_expect_success \
-	'Query "master@May 25 2005" (before history)' \
+	'Query "master@{May 25 2005}" (before history)' \
 	'rm -f o e
-	 git-rev-parse --verify "master@May 25 2005" >o 2>e &&
+	 git-rev-parse --verify "master@{May 25 2005}" >o 2>e &&
 	 test $C = $(cat o) &&
 	 test "warning: Log .git/logs/$m only goes back to $ed." = "$(cat e)"'
 test_expect_success \
-	"Query master@2005-05-25 (before history)" \
+	"Query master@{2005-05-25} (before history)" \
 	'rm -f o e
-	 git-rev-parse --verify master@2005-05-25 >o 2>e &&
+	 git-rev-parse --verify master@{2005-05-25} >o 2>e &&
 	 test $C = $(cat o) &&
 	 echo test "warning: Log .git/logs/$m only goes back to $ed." = "$(cat e)"'
 test_expect_success \
-	'Query "master@May 26 2005 23:31:59" (1 second before history)' \
+	'Query "master@{May 26 2005 23:31:59}" (1 second before history)' \
 	'rm -f o e
-	 git-rev-parse --verify "master@May 26 2005 23:31:59" >o 2>e &&
+	 git-rev-parse --verify "master@{May 26 2005 23:31:59}" >o 2>e &&
 	 test $C = $(cat o) &&
 	 test "warning: Log .git/logs/$m only goes back to $ed." = "$(cat e)"'
 test_expect_success \
-	'Query "master@May 26 2005 23:32:00" (exactly history start)' \
+	'Query "master@{May 26 2005 23:32:00}" (exactly history start)' \
 	'rm -f o e
-	 git-rev-parse --verify "master@May 26 2005 23:32:00" >o 2>e &&
+	 git-rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e &&
 	 test $A = $(cat o) &&
 	 test "" = "$(cat e)"'
 test_expect_success \
-	'Query "master@2005-05-26 23:33:01" (middle of history with gap)' \
+	'Query "master@{2005-05-26 23:33:01}" (middle of history with gap)' \
 	'rm -f o e
-	 git-rev-parse --verify "master@2005-05-26 23:33:01" >o 2>e &&
+	 git-rev-parse --verify "master@{2005-05-26 23:33:01}" >o 2>e &&
 	 test $B = $(cat o) &&
 	 test "warning: Log .git/logs/$m has gap after $gd." = "$(cat e)"'
 test_expect_success \
-	'Query "master@2005-05-26 23:33:01" (middle of history)' \
+	'Query "master@{2005-05-26 23:38:00}" (middle of history)' \
 	'rm -f o e
-	 git-rev-parse --verify "master@2005-05-26 23:38:00" >o 2>e &&
+	 git-rev-parse --verify "master@{2005-05-26 23:38:00}" >o 2>e &&
 	 test $Z = $(cat o) &&
 	 test "" = "$(cat e)"'
 test_expect_success \
-	'Query "master@2005-05-26 23:43:00" (exact end of history)' \
+	'Query "master@{2005-05-26 23:43:00}" (exact end of history)' \
 	'rm -f o e
-	 git-rev-parse --verify "master@2005-05-26 23:43:00" >o 2>e &&
+	 git-rev-parse --verify "master@{2005-05-26 23:43:00}" >o 2>e &&
 	 test $E = $(cat o) &&
 	 test "" = "$(cat e)"'
 test_expect_success \
-	'Query "master@2005-05-28" (past end of history)' \
+	'Query "master@{2005-05-28}" (past end of history)' \
 	'rm -f o e
-	 git-rev-parse --verify "master@2005-05-28" >o 2>e &&
+	 git-rev-parse --verify "master@{2005-05-28}" >o 2>e &&
 	 test $D = $(cat o) &&
 	 test "warning: Log .git/logs/$m unexpectedly ended on $ld." = "$(cat e)"'
 
+
+rm -f .git/$m .git/logs/$m expect
+
+test_expect_success \
+    'creating initial files' \
+    'cp ../../COPYING COPYING &&
+     git-add COPYING &&
+	 GIT_COMMITTER_DATE="2005-05-26 23:30" git-commit -m add -a &&
+	 cp ../../Makefile COPYING &&
+	 GIT_COMMITTER_DATE="2005-05-26 23:41" git-commit -m change -a'
+
+test_expect_success \
+	'git-cat-file blob master:COPYING (expect Makefile)' \
+	'git-cat-file blob master:COPYING | diff - ../../Makefile'
+test_expect_success \
+	'git-cat-file blob master@{2005-05-26 23:30}:COPYING (expect COPYING)' \
+	'git-cat-file blob "master@{2005-05-26 23:30}:COPYING" \
+	  | diff - ../../COPYING'
+test_expect_success \
+	'git-cat-file blob master@{2005-05-26 23:42}:COPYING (expect Makefile)' \
+	'git-cat-file blob "master@{2005-05-26 23:42}:COPYING" \
+	  | diff - ../../Makefile'
+
 test_done
-- 
1.3.2.g7278

^ permalink raw reply related

* [PATCH 4/5] Log ref updates made by fetch.
From: Shawn Pearce @ 2006-05-19  7:29 UTC (permalink / raw)
  To: Junio Hamano; +Cc: git

If a ref is changed by http-fetch, local-fetch or ssh-fetch
record the change and the remote URL/name in the log for the ref.
This requires loading the config file to check logAllRefUpdates.

Also fixed a bug in the ref lock generation; the log file name was
not being produced right due to a bad prefix length.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

---

 fetch.c       |   17 +++++++++++++++--
 fetch.h       |    3 +++
 http-fetch.c  |    2 ++
 local-fetch.c |    2 ++
 refs.c        |    5 +++--
 ssh-fetch.c   |    2 ++
 6 files changed, 27 insertions(+), 4 deletions(-)

b929e2a5a8f80c8635cf3c54a6d766902cf87434
diff --git a/fetch.c b/fetch.c
index 8bdaacb..fd57684 100644
--- a/fetch.c
+++ b/fetch.c
@@ -8,6 +8,7 @@ #include "blob.h"
 #include "refs.h"
 
 const char *write_ref = NULL;
+const char *write_ref_log_details = NULL;
 
 const unsigned char *current_ref = NULL;
 
@@ -206,13 +207,17 @@ int pull(char *target)
 {
 	struct ref_lock *lock;
 	unsigned char sha1[20];
+	char *msg;
+	int ret;
 
 	save_commit_buffer = 0;
 	track_object_refs = 0;
 	if (write_ref) {
 		lock = lock_ref_sha1(write_ref, current_ref, 1);
-		if (!lock)
+		if (!lock) {
+			error("Can't lock ref %s", write_ref);
 			return -1;
+		}
 	}
 
 	if (!get_recover) {
@@ -234,7 +239,15 @@ int pull(char *target)
 	}
 
 	if (write_ref) {
-		return write_ref_sha1(lock, sha1, "git fetch");
+		if (write_ref_log_details) {
+			msg = xmalloc(strlen(write_ref_log_details) + 12);
+			sprintf(msg, "fetch from %s", write_ref_log_details);
+		} else
+			msg = NULL;
+		ret = write_ref_sha1(lock, sha1, msg ? msg : "fetch (unknown)");
+		if (msg)
+			free(msg);
+		return ret;
 	}
 	return 0;
 }
diff --git a/fetch.h b/fetch.h
index 9837a3d..0011548 100644
--- a/fetch.h
+++ b/fetch.h
@@ -25,6 +25,9 @@ extern int fetch_ref(char *ref, unsigned
 /* If set, the ref filename to write the target value to. */
 extern const char *write_ref;
 
+/* If set additional text will appear in the ref log. */
+extern const char *write_ref_log_details;
+
 /* If set, the hash that the current value of write_ref must be. */
 extern const unsigned char *current_ref;
 
diff --git a/http-fetch.c b/http-fetch.c
index 861644b..cc7bd1f 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -1223,6 +1223,7 @@ int main(int argc, char **argv)
 	int rc = 0;
 
 	setup_git_directory();
+	git_config(git_default_config);
 
 	while (arg < argc && argv[arg][0] == '-') {
 		if (argv[arg][1] == 't') {
@@ -1249,6 +1250,7 @@ int main(int argc, char **argv)
 	}
 	commit_id = argv[arg];
 	url = argv[arg + 1];
+	write_ref_log_details = url;
 
 	http_init();
 
diff --git a/local-fetch.c b/local-fetch.c
index fa9e697..ffa4887 100644
--- a/local-fetch.c
+++ b/local-fetch.c
@@ -208,6 +208,7 @@ int main(int argc, char **argv)
 	int arg = 1;
 
 	setup_git_directory();
+	git_config(git_default_config);
 
 	while (arg < argc && argv[arg][0] == '-') {
 		if (argv[arg][1] == 't')
@@ -239,6 +240,7 @@ int main(int argc, char **argv)
 		usage(local_pull_usage);
 	commit_id = argv[arg];
 	path = argv[arg + 1];
+	write_ref_log_details = path;
 
 	if (pull(commit_id))
 		return 1;
diff --git a/refs.c b/refs.c
index 31cf276..d3ddc82 100644
--- a/refs.c
+++ b/refs.c
@@ -142,6 +142,8 @@ static int do_for_each_ref(const char *b
 			namelen = strlen(de->d_name);
 			if (namelen > 255)
 				continue;
+			if (namelen>5 && !strcmp(de->d_name+namelen-5,".lock"))
+				continue;
 			memcpy(path + baselen, de->d_name, namelen+1);
 			if (stat(git_path("%s", path), &st) < 0)
 				continue;
@@ -296,7 +298,6 @@ static struct ref_lock* lock_ref_sha1_ba
 	plen = strlen(path) - plen;
 	path = resolve_ref(path, lock->old_sha1, mustexist);
 	if (!path) {
-		error("Can't read ref %s", path);
 		unlock_ref(lock);
 		return NULL;
 	}
@@ -326,7 +327,7 @@ struct ref_lock* lock_ref_sha1(const cha
 	if (check_ref_format(ref))
 		return NULL;
 	return lock_ref_sha1_basic(git_path("refs/%s", ref),
-		strlen(ref), old_sha1, mustexist);
+		5 + strlen(ref), old_sha1, mustexist);
 }
 
 struct ref_lock* lock_any_ref_for_update(const char *ref,
diff --git a/ssh-fetch.c b/ssh-fetch.c
index 4eb9e04..e3067b8 100644
--- a/ssh-fetch.c
+++ b/ssh-fetch.c
@@ -132,6 +132,7 @@ int main(int argc, char **argv)
 	if (!prog) prog = "git-ssh-upload";
 
 	setup_git_directory();
+	git_config(git_default_config);
 
 	while (arg < argc && argv[arg][0] == '-') {
 		if (argv[arg][1] == 't') {
@@ -158,6 +159,7 @@ int main(int argc, char **argv)
 	}
 	commit_id = argv[arg];
 	url = argv[arg + 1];
+	write_ref_log_details = url;
 
 	if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1))
 		return 1;
-- 
1.3.2.g7278

^ permalink raw reply related

* [PATCH 3/5] Force writing ref if it doesn't exist.
From: Shawn Pearce @ 2006-05-19  7:29 UTC (permalink / raw)
  To: Junio Hamano; +Cc: git

Normally we try to skip writing a ref if its value hasn't changed
but in the special case that the ref doesn't exist but the new
value is going to be 0{40} then force writing the ref anyway.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

---

 refs.c |    4 +++-
 refs.h |    1 +
 2 files changed, 4 insertions(+), 1 deletions(-)

13f3c9a2b8959da1947e21c32e58d81d32a83f3e
diff --git a/refs.c b/refs.c
index 9d37a02..31cf276 100644
--- a/refs.c
+++ b/refs.c
@@ -288,6 +288,7 @@ static struct ref_lock* lock_ref_sha1_ba
 	const unsigned char *old_sha1, int mustexist)
 {
 	struct ref_lock *lock;
+	struct stat st;
 
 	lock = xcalloc(1, sizeof(struct ref_lock));
 	lock->lock_fd = -1;
@@ -303,6 +304,7 @@ static struct ref_lock* lock_ref_sha1_ba
 	lock->ref_file = strdup(path);
 	lock->lock_file = strdup(mkpath("%s.lock", lock->ref_file));
 	lock->log_file = strdup(git_path("logs/%s", lock->ref_file + plen));
+	lock->force_write = !lstat(lock->ref_file, &st) || errno == ENOENT;
 
 	if (safe_create_leading_directories(lock->lock_file))
 		die("unable to create directory for %s", lock->lock_file);
@@ -405,7 +407,7 @@ int write_ref_sha1(struct ref_lock *lock
 
 	if (!lock)
 		return -1;
-	if (!memcmp(lock->old_sha1, sha1, 20)) {
+	if (!lock->force_write && !memcmp(lock->old_sha1, sha1, 20)) {
 		unlock_ref(lock);
 		return 0;
 	}
diff --git a/refs.h b/refs.h
index 2c854de..6c946ea 100644
--- a/refs.h
+++ b/refs.h
@@ -7,6 +7,7 @@ struct ref_lock {
 	char *log_file;
 	unsigned char old_sha1[20];
 	int lock_fd;
+	int force_write;
 };
 
 /*
-- 
1.3.2.g7278

^ permalink raw reply related

* [PATCH 2/5] Added logs/ directory to repository layout.
From: Shawn Pearce @ 2006-05-19  7:28 UTC (permalink / raw)
  To: Junio Hamano; +Cc: git


Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

---

 Documentation/repository-layout.txt |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

27faccbeae368625d4a11788e5cedc7b3dc23f54
diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt
index 98fbe7d..b52dfdc 100644
--- a/Documentation/repository-layout.txt
+++ b/Documentation/repository-layout.txt
@@ -128,3 +128,14 @@ remotes::
 	Stores shorthands to be used to give URL and default
 	refnames to interact with remote repository to `git
 	fetch`, `git pull` and `git push` commands.
+
+logs::
+	Records of changes made to refs are stored in this
+	directory.  See the documentation on git-update-ref
+	for more information.
+
+logs/refs/heads/`name`::
+	Records all changes made to the branch tip named `name`.
+
+logs/refs/tags/`name`::
+	Records all changes made to the tag named `name`.
-- 
1.3.2.g7278

^ permalink raw reply related

* [PATCH 1/5] General ref log reading improvements.
From: Shawn Pearce @ 2006-05-19  7:28 UTC (permalink / raw)
  To: Junio Hamano; +Cc: git

Corrected the log starting time displayed in the error message
(as it was always showing the epoch due to a bad input to strtoul).

Improved the log parser so we only scan backwards towards the
'\n' from the end of the prior log; during this scan the last '>'
is remembered to improve performance (rather than scanning forward
to it).

If the log record matched is the last log record in the file only
use its new sha1 value if the date matches exactly; otherwise we
leave the passed in sha1 alone as it already contains the current
value of the ref.  This way lookups of dates later than the log
end to stick with the current ref value in case the ref was updated
without logging.

If it looks like someone changed the ref without logging it and we
are going to return the sha1 which should have been valid during
the missing period then warn the user that there might be log data
missing and thus their query result may not be accurate.  The check
isn't perfect as its just based on comparing the old and new sha1
values between the two log records but its better than not checking
at all.

Implemented test cases based on git-rev-parse for most of the
boundary conditions.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

---

 refs.c                |   54 +++++++++++++++++++++++++++++++----------
 t/t1400-update-ref.sh |   64 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+), 14 deletions(-)
 mode change 100644 => 100755 t/t1400-update-ref.sh

54717d099405378da50cd3d4715c1e5d6d793d68
diff --git a/refs.c b/refs.c
index ae9825d..9d37a02 100644
--- a/refs.c
+++ b/refs.c
@@ -432,11 +432,12 @@ int write_ref_sha1(struct ref_lock *lock
 
 int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1)
 {
-	const char *logfile, *logdata, *logend, *rec, *c;
+	const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
 	char *tz_c;
 	int logfd, tz;
 	struct stat st;
 	unsigned long date;
+	unsigned char logged_sha1[20];
 
 	logfile = git_path("logs/%s", ref);
 	logfd = open(logfile, O_RDONLY, 0);
@@ -448,32 +449,57 @@ int read_ref_at(const char *ref, unsigne
 	logdata = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0);
 	close(logfd);
 
+	lastrec = NULL;
 	rec = logend = logdata + st.st_size;
 	while (logdata < rec) {
 		if (logdata < rec && *(rec-1) == '\n')
 			rec--;
-		while (logdata < rec && *(rec-1) != '\n')
+		lastgt = NULL;
+		while (logdata < rec && *(rec-1) != '\n') {
 			rec--;
-		c = rec;
-		while (c < logend && *c != '>' && *c != '\n')
-			c++;
-		if (c == logend || *c == '\n')
+			if (*rec == '>')
+				lastgt = rec;
+		}
+		if (!lastgt)
 			die("Log %s is corrupt.", logfile);
-		date = strtoul(c + 1, NULL, 10);
+		date = strtoul(lastgt + 1, &tz_c, 10);
 		if (date <= at_time) {
-			if (get_sha1_hex(rec + 41, sha1))
-				die("Log %s is corrupt.", logfile);
+			if (lastrec) {
+				if (get_sha1_hex(lastrec, logged_sha1))
+					die("Log %s is corrupt.", logfile);
+				if (get_sha1_hex(rec + 41, sha1))
+					die("Log %s is corrupt.", logfile);
+				if (memcmp(logged_sha1, sha1, 20)) {
+					tz = strtoul(tz_c, NULL, 10);
+					fprintf(stderr,
+						"warning: Log %s has gap after %s.\n",
+						logfile, show_rfc2822_date(date, tz));
+				}
+			} else if (date == at_time) {
+				if (get_sha1_hex(rec + 41, sha1))
+					die("Log %s is corrupt.", logfile);
+			} else {
+				if (get_sha1_hex(rec + 41, logged_sha1))
+					die("Log %s is corrupt.", logfile);
+				if (memcmp(logged_sha1, sha1, 20)) {
+					tz = strtoul(tz_c, NULL, 10);
+					fprintf(stderr,
+						"warning: Log %s unexpectedly ended on %s.\n",
+						logfile, show_rfc2822_date(date, tz));
+				}
+			}
 			munmap((void*)logdata, st.st_size);
 			return 0;
 		}
+		lastrec = rec;
 	}
 
-	c = logdata;
-	while (c < logend && *c != '>' && *c != '\n')
-		c++;
-	if (c == logend || *c == '\n')
+	rec = logdata;
+	while (rec < logend && *rec != '>' && *rec != '\n')
+		rec++;
+	if (rec == logend || *rec == '\n')
 		die("Log %s is corrupt.", logfile);
-	date = strtoul(c, &tz_c, 10);
+	date = strtoul(rec + 1, &tz_c, 10);
 	tz = strtoul(tz_c, NULL, 10);
 	if (get_sha1_hex(logdata, sha1))
 		die("Log %s is corrupt.", logfile);
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
old mode 100644
new mode 100755
index f338c53..7858d86
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -9,6 +9,10 @@ test_description='Test git-update-ref an
 Z=0000000000000000000000000000000000000000
 A=1111111111111111111111111111111111111111
 B=2222222222222222222222222222222222222222
+C=3333333333333333333333333333333333333333
+D=4444444444444444444444444444444444444444
+E=5555555555555555555555555555555555555555
+F=6666666666666666666666666666666666666666
 m=refs/heads/master
 
 test_expect_success \
@@ -109,4 +113,64 @@ test_expect_success \
 	'diff expect .git/logs/$m'
 rm -f .git/$m .git/logs/$m expect
 
+git-update-ref $m $D
+cat >.git/logs/$m <<EOF
+$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+$A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500
+$F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500
+$Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500
+EOF
+
+ed="Thu, 26 May 2005 18:32:00 -0500"
+gd="Thu, 26 May 2005 18:33:00 -0500"
+ld="Thu, 26 May 2005 18:43:00 -0500"
+test_expect_success \
+	'Query "master@May 25 2005" (before history)' \
+	'rm -f o e
+	 git-rev-parse --verify "master@May 25 2005" >o 2>e &&
+	 test $C = $(cat o) &&
+	 test "warning: Log .git/logs/$m only goes back to $ed." = "$(cat e)"'
+test_expect_success \
+	"Query master@2005-05-25 (before history)" \
+	'rm -f o e
+	 git-rev-parse --verify master@2005-05-25 >o 2>e &&
+	 test $C = $(cat o) &&
+	 echo test "warning: Log .git/logs/$m only goes back to $ed." = "$(cat e)"'
+test_expect_success \
+	'Query "master@May 26 2005 23:31:59" (1 second before history)' \
+	'rm -f o e
+	 git-rev-parse --verify "master@May 26 2005 23:31:59" >o 2>e &&
+	 test $C = $(cat o) &&
+	 test "warning: Log .git/logs/$m only goes back to $ed." = "$(cat e)"'
+test_expect_success \
+	'Query "master@May 26 2005 23:32:00" (exactly history start)' \
+	'rm -f o e
+	 git-rev-parse --verify "master@May 26 2005 23:32:00" >o 2>e &&
+	 test $A = $(cat o) &&
+	 test "" = "$(cat e)"'
+test_expect_success \
+	'Query "master@2005-05-26 23:33:01" (middle of history with gap)' \
+	'rm -f o e
+	 git-rev-parse --verify "master@2005-05-26 23:33:01" >o 2>e &&
+	 test $B = $(cat o) &&
+	 test "warning: Log .git/logs/$m has gap after $gd." = "$(cat e)"'
+test_expect_success \
+	'Query "master@2005-05-26 23:33:01" (middle of history)' \
+	'rm -f o e
+	 git-rev-parse --verify "master@2005-05-26 23:38:00" >o 2>e &&
+	 test $Z = $(cat o) &&
+	 test "" = "$(cat e)"'
+test_expect_success \
+	'Query "master@2005-05-26 23:43:00" (exact end of history)' \
+	'rm -f o e
+	 git-rev-parse --verify "master@2005-05-26 23:43:00" >o 2>e &&
+	 test $E = $(cat o) &&
+	 test "" = "$(cat e)"'
+test_expect_success \
+	'Query "master@2005-05-28" (past end of history)' \
+	'rm -f o e
+	 git-rev-parse --verify "master@2005-05-28" >o 2>e &&
+	 test $D = $(cat o) &&
+	 test "warning: Log .git/logs/$m unexpectedly ended on $ld." = "$(cat e)"'
+
 test_done
-- 
1.3.2.g7278

^ permalink raw reply related

* [PATCH 0/5] Ref log updates
From: Shawn Pearce @ 2006-05-19  7:27 UTC (permalink / raw)
  To: Junio Hamano; +Cc: git

The following series of patches applies on top of 'pu' and my prior
series of ref log related patches.

Most of these are bug fixes and test cases.

* [PATCH 1/5] General ref log reading improvements.

	Performance improvements and minor bug fixes in the log
	parser.

* [PATCH 2/5] Added logs/ directory to repository layout.

	Minor documentation update that I missed in the last round.

* [PATCH 3/5] Force writing ref if it doesn't exist.

	If a ref doesn't exist make sure we write it anyway.
	I found a few cases were we weren't writing the ref; this
	appears to have it fixed.

* [PATCH 4/5] Log ref updates made by fetch.

	Fully enable ref logging for the *-fetch family of tools.

* [PATCH 5/5] Change 'master@noon' syntax to 'master@{noon}'.

	Support parsing ':' in date strings correctly, especially
	in the face of 'master@2005-06-12 16:12:foo'.

-- 
Shawn.

^ permalink raw reply

* FIXED: [WARNING] Please be careful when using "git add" from "next" branch
From: Junio C Hamano @ 2006-05-19  6:28 UTC (permalink / raw)
  To: git; +Cc: linux-kernel
In-Reply-To: <7vsln74sv7.fsf_-_@assigned-by-dhcp.cox.net>

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

> There is still a small breakage in the built-in "git add" on the
> "next" branch that ends up creating nonsense tree objects.

This was fixed this morning, in case I scared people.
 

^ permalink raw reply

* Re: [PATCH] Allow pickaxe and diff-filter options to be used by git log.
From: Junio C Hamano @ 2006-05-19  6:05 UTC (permalink / raw)
  To: Sean; +Cc: git
In-Reply-To: <BAYC1-PASMTP092CB0667E05EA20FBA30EAEA70@CEZ.ICE>

Sean <seanlkml@sympatico.ca> writes:

> Well, I was looking at the use of diff-filter and -S as a way
> to prune uninteresting commits from the log rather than as an 
> desire to see the patch information.

Fair enough.

> It's pretty natural to add -p or --stat along with the above 
> options if that is what the user wants.  If you make those implied
> by using --diff-filter or -S is there a way for the user to say,
> no patch and no stat?

Well, I was sneaking in a hidden feature with that tweak.

Regardless of the diff-filter/-S issues, with that alternative
patch, you could do:

	$ git log -r

It lets you do a wonderful thing with surprisingly small number
of keystrokes ;-).

^ permalink raw reply

* Re: [PATCH] Allow pickaxe and diff-filter options to be used by git log.
From: Sean @ 2006-05-19  5:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vbqtuk1uw.fsf@assigned-by-dhcp.cox.net>

On Thu, 18 May 2006 22:41:43 -0700
Junio C Hamano <junkio@cox.net> wrote:

> To me, if the user explicitly says --diff-filter or -S, it seems
> more natural to interpret that the user wanted _some_ sort of
> diff.  Now, there are people who say raw format is anti-human,
> which I consider is a valid view, but I think it is better than
> NO_OUTPUT in that case.
> 
> I wonder if doing something like this instead makes more sense
> perhaps?

Well, I was looking at the use of diff-filter and -S as a way
to prune uninteresting commits from the log rather than as an 
desire to see the patch information.

It's pretty natural to add -p or --stat along with the above 
options if that is what the user wants.  If you make those implied
by using --diff-filter or -S is there a way for the user to say,
no patch and no stat?

Sean

^ permalink raw reply

* Re: [PATCH] built-in tar-tree and remote tar-tree
From: Junio C Hamano @ 2006-05-19  5:50 UTC (permalink / raw)
  To: git
In-Reply-To: <7vodxulnqx.fsf_-_@assigned-by-dhcp.cox.net>

Sorry for sending a crapoid that does not even compile.  I ran
format-patch while on a wrong branch.

Tonight's "pu" will have a fixed up one for people who are
interested to play with.

^ permalink raw reply

* Re: [PATCH] Allow pickaxe and diff-filter options to be used by git log.
From: Junio C Hamano @ 2006-05-19  5:41 UTC (permalink / raw)
  To: Sean; +Cc: git
In-Reply-To: <BAYC1-PASMTP096010F052E9BF78B5FD4AAEA70@CEZ.ICE>

Sean <seanlkml@sympatico.ca> writes:

> +	if (rev->always_show_header) {
> +		if (rev->diffopt.pickaxe || rev->diffopt.filter) {

I understand and agree to the change up to this part, but I do
not necessarily agree with what follows:

> +			rev->always_show_header = 0;
> +			if (rev->diffopt.output_format == DIFF_FORMAT_RAW)
> +				rev->diffopt.output_format = DIFF_FORMAT_NO_OUTPUT;

To me, if the user explicitly says --diff-filter or -S, it seems
more natural to interpret that the user wanted _some_ sort of
diff.  Now, there are people who say raw format is anti-human,
which I consider is a valid view, but I think it is better than
NO_OUTPUT in that case.

I wonder if doing something like this instead makes more sense
perhaps?

-- >8 --

diff --git a/builtin-log.c b/builtin-log.c
index 69f2911..e68bfad 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -23,6 +23,35 @@ static int cmd_log_wc(int argc, const ch
 	if (argc > 1)
 		die("unrecognized argument: %s", argv[1]);
 
+	if (rev->always_show_header) {
+		/* Log command is primarily about the message for human
+		 * consumption, but if the user asks for any diff, it
+		 * is human unfriendly to give the raw diff.
+		 *
+		 * Show command is the same way, but there the default is
+		 * always give patch output, so this does not trigger.
+		 */
+		if (rev->diffopt.output_format == DIFF_FORMAT_RAW) {
+			if (rev->diffopt.pickaxe)
+				rev->diffopt.output_format = DIFF_FORMAT_PATCH;
+			else {
+				rev->diffopt.output_format = DIFF_FORMAT_DIFFSTAT;
+				rev->diffopt.summary = 1;
+			}
+		}
+
+		/* If the user is limiting the commits to the ones
+		 * that have particular classes of diff, we should not
+		 * show the log message for irrelevant ones.
+		 *
+		 * git show --diff-filter=R -M --all can be used to view
+		 * the branch tips that renames something.  I do not know
+		 * how useful that is, though.
+		 */
+		if (rev->diffopt.pickaxe || rev->diffopt.filter)
+			rev->always_show_header = 0;
+	}
+
 	prepare_revision_walk(rev);
 	setup_pager();
 	while ((commit = get_revision(rev)) != NULL) {

^ permalink raw reply related

* [PATCH] Allow pickaxe and diff-filter options to be used by git log.
From: Sean @ 2006-05-19  4:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vac9elm2p.fsf@assigned-by-dhcp.cox.net>

Handle the -S option when passed to git log such that only the
appropriate commits are displayed.  Also per Junio's comments, do
the same for "--diff-filter", so that it too can be used as an option
to git log.  By default no patch or diff information is displayed.

Signed-off-by: Sean Estabrooks <seanlkml@sympatico.ca>

---

> If your goal is to make whatchanged less necessary, I think you
> would need to special case --diff-filter as well for "git log",
> although nobody on #git channel seems to have noticed.  I often
> run --diff-filter=A when I am trying to see when I added a
> particular file, to avoid getting distracted by other types of
> changes; log would be still shown if do not disable --always.

Makes sense.  This patch should cover that case too.

Sean


a2221c07a94bc378ef40182fa6b260ac88804073
 builtin-log.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

a2221c07a94bc378ef40182fa6b260ac88804073
diff --git a/builtin-log.c b/builtin-log.c
index d5bbc1c..12a6d19 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -23,6 +23,13 @@ static int cmd_log_wc(int argc, const ch
 	rev->commit_format = CMIT_FMT_DEFAULT;
 	rev->verbose_header = 1;
 	argc = setup_revisions(argc, argv, rev, "HEAD");
+	if (rev->always_show_header) {
+		if (rev->diffopt.pickaxe || rev->diffopt.filter) {
+			rev->always_show_header = 0;
+			if (rev->diffopt.output_format == DIFF_FORMAT_RAW)
+				rev->diffopt.output_format = DIFF_FORMAT_NO_OUTPUT;
+		}
+	}
 
 	if (argc > 1)
 		die("unrecognized argument: %s", argv[1]);
-- 
1.3.GIT

^ permalink raw reply related

* Re: [PATCH] Allow pickaxe to be used via git log.
From: Sean @ 2006-05-19  3:38 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vk68ilnoi.fsf@assigned-by-dhcp.cox.net>

On Thu, 18 May 2006 20:05:01 -0700
Junio C Hamano <junkio@cox.net> wrote:


> User's scripts.  The point is the set of arguments rev-list as
> the lowest level machinery should not be modified by an
> arbitrary policy decision that happens to suit "git log" usage.
> 

Okay, thanks.

This moves the policy up a level and into the log/show/whatchanged code
and makes the code match the commit message better.  However, it will still
"disobey" user options if the user tries to combine both pickaxe and
--always for these commands; but hopefully that's okay at this level.

Sean

diff --git a/builtin-log.c b/builtin-log.c
index d5bbc1c..d2c3df0 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -23,6 +23,11 @@ static int cmd_log_wc(int argc, const ch
 	rev->commit_format = CMIT_FMT_DEFAULT;
 	rev->verbose_header = 1;
 	argc = setup_revisions(argc, argv, rev, "HEAD");
+	if (rev->diffopt.pickaxe && rev->always_show_header) {
+		rev->always_show_header = 0;
+		if (rev->diffopt.output_format == DIFF_FORMAT_RAW)
+			rev->diffopt.output_format = DIFF_FORMAT_NO_OUTPUT;
+	}
 
 	if (argc > 1)
 		die("unrecognized argument: %s", argv[1]);

^ permalink raw reply related

* Re: [PATCH] Allow pickaxe to be used via git log.
From: Junio C Hamano @ 2006-05-19  3:39 UTC (permalink / raw)
  To: Sean; +Cc: git
In-Reply-To: <BAYC1-PASMTP04945C92FB14DA65AB1AC7AEA70@CEZ.ICE>

Sean <seanlkml@sympatico.ca> writes:

> Handle the -S option when passed to git log such that only the appropriate
> commits are displayed.  Unlike "whatchanged", by default no diff output
> is produced.

If your goal is to make whatchanged less necessary, I think you
would need to special case --diff-filter as well for "git log",
although nobody on #git channel seems to have noticed.  I often
run --diff-filter=A when I am trying to see when I added a
particular file, to avoid getting distracted by other types of
changes; log would be still shown if do not disable --always.

^ permalink raw reply

* Re: [PATCH] Allow pickaxe to be used via git log.
From: Junio C Hamano @ 2006-05-19  3:05 UTC (permalink / raw)
  To: git
In-Reply-To: <BAYC1-PASMTP07581788E7BAAC19B2A159AEA70@CEZ.ICE>

Sean <seanlkml@sympatico.ca> writes:

> Is there any place that depends on the ability to specify both a pickaxe
> string _and_ always_show_header?  If not, it's hard to see how this patch
> could break anything.

User's scripts.  The point is the set of arguments rev-list as
the lowest level machinery should not be modified by an
arbitrary policy decision that happens to suit "git log" usage.

^ permalink raw reply

* [PATCH] built-in tar-tree and remote tar-tree
From: Junio C Hamano @ 2006-05-19  3:03 UTC (permalink / raw)
  To: git
In-Reply-To: <20060518192144.15912.qmail@web25913.mail.ukl.yahoo.com>

This makes tar-tree a built-in.  As an added bonus, you can now
say:

	git tar-tree --remote=remote-repository <ent> [<base>]

This does not work with git-daemon yet, but should work with
localhost and git over ssh transports.

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

---

 * It comes up every once in a while that somebody says he wants
   a shallow clone, but when asked "what for?" it turns out that
   what is wanted is the ability to download a tarball for a
   specific revision for building that version, so here is one.

   If people think this is a useful thing, we would need to
   teach git-daemon about git-upload-tar, and perhaps we would
   also want to compress the tar image while it goes over the
   wire, which would be more work.

 Makefile                         |    8 +++--
 tar-tree.c => builtin-tar-tree.c |   62 +++++++++++++++++++++++++++++++++++-
 builtin-upload-tar.c             |   66 ++++++++++++++++++++++++++++++++++++++
 builtin.h                        |    2 +
 git.c                            |    2 +
 5 files changed, 135 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index 2149fb8..caf1e70 100644
--- a/Makefile
+++ b/Makefile
@@ -161,7 +161,7 @@ PROGRAMS = \
 	git-receive-pack$X git-rev-parse$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-ssh-upload$X git-unpack-file$X \
 	git-unpack-objects$X git-update-index$X git-update-server-info$X \
 	git-upload-pack$X git-verify-pack$X git-write-tree$X \
 	git-update-ref$X git-symbolic-ref$X \
@@ -170,7 +170,8 @@ PROGRAMS = \
 
 BUILT_INS = git-log$X git-whatchanged$X git-show$X \
 	git-count-objects$X git-diff$X git-push$X \
-	git-grep$X git-rev-list$X git-check-ref-format$X
+	git-grep$X git-rev-list$X git-check-ref-format$X \
+	git-tar-tree$X git-upload-tar$X
 
 # what 'all' will build and 'install' will install, in gitexecdir
 ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
@@ -218,7 +219,8 @@ LIB_OBJS = \
 
 BUILTIN_OBJS = \
 	builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \
-	builtin-grep.o builtin-rev-list.o builtin-check-ref-format.o
+	builtin-grep.o builtin-rev-list.o builtin-check-ref-format.o \
+	builtin-tar-tree.o builtin-upload-tar.o
 
 GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
 LIBS = $(GITLIBS) -lz
diff --git a/tar-tree.c b/builtin-tar-tree.c
similarity index 86%
rename from tar-tree.c
rename to builtin-tar-tree.c
index 3308736..e97e0af 100644
--- a/tar-tree.c
+++ b/builtin-tar-tree.c
@@ -7,11 +7,14 @@ #include "tree-walk.h"
 #include "commit.h"
 #include "strbuf.h"
 #include "tar.h"
+#include "builtin.h"
+#include "pkt-line.h"
 
 #define RECORDSIZE	(512)
 #define BLOCKSIZE	(RECORDSIZE * 20)
 
-static const char tar_tree_usage[] = "git-tar-tree <key> [basedir]";
+static const char tar_tree_usage[] =
+"git-tar-tree [--remote=<repo>] <ent> [basedir]";
 
 static char block[BLOCKSIZE];
 static unsigned long offset;
@@ -301,7 +304,7 @@ static void traverse_tree(struct tree_de
 	}
 }
 
-int main(int argc, char **argv)
+int generate_tar(int argc, const char **argv)
 {
 	unsigned char sha1[20], tree_sha1[20];
 	struct commit *commit;
@@ -348,3 +351,58 @@ int main(int argc, char **argv)
 	free(current_path.buf);
 	return 0;
 }
+
+static const char *exec = "git-upload-tar";
+
+static int remote_tar(int argc, const char **argv)
+{
+	int fd[2], ret, len;
+	pid_t pid;
+	char buf[1024];
+	char *url;
+
+	if (argc < 3 || 4 < argc)
+		usage(tar_tree_usage);
+
+	/* --remote=<repo> */
+	url = strdup(argv[1]+9);
+	pid = git_connect(fd, url, exec);
+	if (pid < 0)
+		return 1;
+
+	packet_write(fd[1], "want %s\n", argv[2]);
+	if (argv[3])
+		packet_write(fd[1], "base %s\n", argv[3]);
+	packet_flush(fd[1]);
+
+	len = packet_read_line(fd[0], buf, sizeof(buf));
+	if (!len)
+		die("git-tar-tree: expected ACK/NAK, got EOF");
+	if (buf[len-1] == '\n')
+		buf[--len] = 0;
+	if (strcmp(buf, "ACK")) {
+		if (5 < len && !strncmp(buf, "NACK ", 5))
+			die("git-tar-tree: NACK %s", buf + 5);
+		die("git-tar-tree: protocol error");
+	}
+	/* expect a flush */
+	len = packet_read_line(fd[0], buf, sizeof(buf));
+	if (len)
+		die("git-tar-tree: expected a flush");
+
+	/* Now, start reading from fd[0] and spit it out to stdout */
+	ret = copy_fd(fd[0], 1);
+	close(fd[0]);
+
+	ret |= finish_connect(pid);
+	return !!ret;
+}
+
+int cmd_tar_tree(int argc, const char **argv, char **envp)
+{
+	if (argc < 2)
+		usage(tar_tree_usage);
+	if (!strncmp("--remote=", argv[1], 9))
+		return remote_tar(argc, argv);
+	return generate_tar(argc, argv);
+}
diff --git a/builtin-upload-tar.c b/builtin-upload-tar.c
new file mode 100644
index 0000000..883b5aa
--- /dev/null
+++ b/builtin-upload-tar.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006 Junio C Hamano
+ */
+#include "cache.h"
+#include "pkt-line.h"
+#include "exec_cmd.h"
+#include "builtin.h"
+
+static const char upload_tar_usage[] = "git-upload-tar <repo>";
+
+static int nack(const char *reason)
+{
+	packet_write(1, "NACK %s\n", reason);
+	packet_flush(1);
+	return 1;
+}
+
+int cmd_upload_tar(int argc, const char **argv, char **envp)
+{
+	int len;
+	char *dir = argv[1];
+	char buf[8129];
+	unsigned char sha1[20];
+	char *base = NULL;
+	char hex[41];
+	int ac;
+	const char *av[4];
+
+	if (argc != 2)
+		usage(upload_tar_usage);
+	if (!enter_repo(dir, 0))
+		return nak("not a git archive", dir);
+	len = packet_read_line(0, buf, sizeof(buf));
+	if (len < 5 || strncmp("want ", buf, 5))
+		return nak("expected want");
+	if (buf[len-1] == '\n')
+		buf[--len] = 0;
+	if (get_sha1(buf + 5, sha1))
+		return nak("expected sha1");
+        strcpy(hex, sha1_to_hex(sha1));
+
+	len = packet_read_line(0, buf, sizeof(buf));
+	if (len) {
+		if (len < 5 || strncmp("base ", buf, 5))
+			return nak("expected (optional) base");
+		if (buf[len-1] == '\n')
+			buf[--len] = 0;
+		base = strdup(buf + 5);
+		len = packet_read_line(0, buf, sizeof(buf));
+	}
+	if (len)
+		return nak("expected flush");
+
+	packet_write(1, "ACK\n");
+	packet_flush(1);
+
+	ac = 0;
+	av[ac++] = "tar-tree";
+	av[ac++] = hex;
+	if (base)
+		av[ac++] = base;
+	av[ac++] = NULL;
+	execv_git_cmd(av);
+	/* should it return that is an error */
+	return 1;
+}
diff --git a/builtin.h b/builtin.h
index ff559de..3ed5d65 100644
--- a/builtin.h
+++ b/builtin.h
@@ -26,5 +26,7 @@ extern int cmd_push(int argc, const char
 extern int cmd_grep(int argc, const char **argv, char **envp);
 extern int cmd_rev_list(int argc, const char **argv, char **envp);
 extern int cmd_check_ref_format(int argc, const char **argv, char **envp);
+extern int cmd_tar_tree(int argc, const char **argv, char **envp);
+extern int cmd_upload_tar(int argc, const char **argv, char **envp);
 
 #endif
diff --git a/git.c b/git.c
index d0650bb..79d81b1 100644
--- a/git.c
+++ b/git.c
@@ -50,6 +50,8 @@ static void handle_internal_command(int 
 		{ "count-objects", cmd_count_objects },
 		{ "diff", cmd_diff },
 		{ "grep", cmd_grep },
+		{ "tar-tree", cmd_tar_tree },
+		{ "upload-tar", cmd_upload_tar },
 		{ "rev-list", cmd_rev_list },
 		{ "check-ref-format", cmd_check_ref_format }
 	};
-- 
1.3.3.gfad60

^ permalink raw reply related

* Re: [PATCH] Allow pickaxe to be used via git log.
From: Sean @ 2006-05-19  2:56 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v4pzmn32g.fsf@assigned-by-dhcp.cox.net>

On Thu, 18 May 2006 19:47:19 -0700
Junio C Hamano <junkio@cox.net> wrote:

> If that (specifically, "when passed to git log") is what you
> want, do all of that in "git log" please.  I haven't checked,
> but I suspect your changes would break git-rev-list and makes it
> disobey the options the user gives it.
> 

Well, it's more general than just git log, but that's primarily where one
would see it.  Essentially the patch is saying that specifying both a
"revs->diffopt.pickaxe" string and "revs->always_show_header" is illegal
and proceeds to use pickaxe instead of the other.

Is there any place that depends on the ability to specify both a pickaxe
string _and_ always_show_header?  If not, it's hard to see how this patch
could break anything.

Sean

^ permalink raw reply

* Re: [PATCH] Allow pickaxe to be used via git log.
From: Junio C Hamano @ 2006-05-19  2:47 UTC (permalink / raw)
  To: Sean; +Cc: git
In-Reply-To: <BAYC1-PASMTP04945C92FB14DA65AB1AC7AEA70@CEZ.ICE>

Sean <seanlkml@sympatico.ca> writes:

> Handle the -S option when passed to git log such that only the appropriate
> commits are displayed.  Unlike "whatchanged", by default no diff output
> is produced.

If that (specifically, "when passed to git log") is what you
want, do all of that in "git log" please.  I haven't checked,
but I suspect your changes would break git-rev-list and makes it
disobey the options the user gives it.

^ permalink raw reply

* [PATCH] Allow pickaxe to be used via git log.
From: Sean @ 2006-05-19  1:31 UTC (permalink / raw)
  To: git

Handle the -S option when passed to git log such that only the appropriate
commits are displayed.  Unlike "whatchanged", by default no diff output
is produced.

---

This came out of recent comments on #git and will hopefully further reduce
the need for git-whatchanged.


ecdfaa21dbff93a6a387b02e1f1d3ebf05ee517d
 revision.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

ecdfaa21dbff93a6a387b02e1f1d3ebf05ee517d
diff --git a/revision.c b/revision.c
index 2294b16..2e18b2b 100644
--- a/revision.c
+++ b/revision.c
@@ -743,6 +743,13 @@ int setup_revisions(int argc, const char
 				continue;
 			}
 			opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
+			if (revs->diffopt.pickaxe && revs->always_show_header) {
+				revs->always_show_header = 0;
+				revs->diff = 1;
+				revs->diffopt.recursive = 1;
+				if (revs->diffopt.output_format == DIFF_FORMAT_RAW)
+					revs->diffopt.output_format = DIFF_FORMAT_NO_OUTPUT;
+			}
 			if (opts > 0) {
 				revs->diff = 1;
 				i += opts - 1;
-- 
1.3.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