Git development
 help / color / mirror / Atom feed
* Re: The git newbie experience
From: Shawn Pearce @ 2006-05-15  5:27 UTC (permalink / raw)
  To: Tommi Virtanen; +Cc: Junio C Hamano, git
In-Reply-To: <44680C54.8040206@inoi.fi>

Tommi Virtanen <tv@inoi.fi> wrote:
> Junio C Hamano wrote:
[snip]
> > - Jack stashes away what he has been working on and cleans up
> >   his mess.
> > 
> >   git diff >P.diff
> >   git checkout HEAD A B C
> ...
> > - Jack then reapplies what he stashed away with "git apply P.diff"
> >   and keeps working.
> > 
> > Maybe "git stash" command that does "git diff --full-index" with
> > some frills, and "git unstash" command which does an equivalent
> > of "git am -3" would help this workflow (bare "git apply" does
> > not do the three-way merge like am does).
> 
> Oh, I'd love to have a quick stash, that's what we actually ended up
> doing a lot. Although I'd rather see a real implementation use a branch
> and not just a diff file, but.. yes please.
> 
> Although, "git stash" and "git unstash" are yet another command to add
> to the newbie set, and I just complained about the size of the set ;)

This is perhaps one area where SVN's user interface is actually nice.
SVN's equiv. of stash is making a copy of your working directory into
the repository; something that is rather simple to do for the user.

What about "git commit -b foo -a" to commit the current working
directory to branch 'foo'?

Then restoring is a pull of foo ("git pull . foo"), but that
intermediate commit is now part of the repository history.  And "git
commit -a" doesn't automatically add extra/other files to the
repository and it probably should in the case of a "stash".

-- 
Shawn.

^ permalink raw reply

* Re: The git newbie experience
From: Junio C Hamano @ 2006-05-15  5:18 UTC (permalink / raw)
  To: Tommi Virtanen; +Cc: git
In-Reply-To: <44680C54.8040206@inoi.fi>

Tommi Virtanen <tv@inoi.fi> writes:

> Oh, I'd love to have a quick stash, that's what we actually ended up
> doing a lot. Although I'd rather see a real implementation use a branch
> and not just a diff file, but.. yes please.

I'd rather do that with a diff file that can be used to do a
3-way (see how rebase does it with --full-index diff with am -3).
No point creating and forgetting to remove a throw away branch
and getting more complaints.

^ permalink raw reply

* Re: The git newbie experience
From: Tommi Virtanen @ 2006-05-15  5:06 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfyjcntro.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:
> Anyway, I think the time to commit is too late to save somebody
> who does not understand the index.  How would you explain why
> you sometimes need to use -A and sometimes -a? 

I guess what I really want is "a smarter -a".

> That is why I
> suggested to make "git pull" and "git merge" refuse to work if
> there are local changes for novice users, where the definition
> of novice is "git commit -a" is the only way to make a commit.
> We can have [core] novice = yes in .git/config for that.
> 
> If somebody does not understand the index, if the merge is
> prevented because the local change does conflict with it, how
> would you explain why sometimes you can merge and sometimes you
> cannot?

By the same logic that is already implemented. "pull refuses to pull
changes to files that are modified but not committed".

>> For example, we had a case where we absolutely _had_ to keep
>> an ugly workaround in the tree, in a file not otherwise
>> edited, but we definitely did not want to commit the kludge,
> Your example is a very ill-thought out one.
>
> If you are leaving the uncommitable kludge around, you cannot be
> using "commit -a" with the normal non-merge workflow.  Why
> would you worry about not being able to do "commit -a" on a
> merge then?

The indexless working mode means you know two kinds of commits.
"git commit -a" or "git commit FILE..". The uncommitted kludge hanging
around means people listed file names. The case where the merge differs
is that it's not just a few files, and they didn't even really
know what files to list. And "git status" showed them something
they were not used to seeing.

> For the beginning user without index, I would rewrite your
> scenario like this.
> 
...
> - Jack stashes away what he has been working on and cleans up
>   his mess.
> 
>   git diff >P.diff
>   git checkout HEAD A B C
...
> - Jack then reapplies what he stashed away with "git apply P.diff"
>   and keeps working.
> 
> Maybe "git stash" command that does "git diff --full-index" with
> some frills, and "git unstash" command which does an equivalent
> of "git am -3" would help this workflow (bare "git apply" does
> not do the three-way merge like am does).

Oh, I'd love to have a quick stash, that's what we actually ended up
doing a lot. Although I'd rather see a real implementation use a branch
and not just a diff file, but.. yes please.

Although, "git stash" and "git unstash" are yet another command to add
to the newbie set, and I just complained about the size of the set ;)

-- 
Inoi Oy, Tykistökatu 4 D (4. krs), FI-20520 Turku, Finland
http://www.inoi.fi/
Mobile +358 40 762 5656

^ permalink raw reply

* Re: [PATCH (resend)] send-email: address expansion for common mailers
From: Ryan Anderson @ 2006-05-15  4:12 UTC (permalink / raw)
  To: Eric Wong; +Cc: Junio C Hamano, git, Ryan Anderson
In-Reply-To: <11476592243181-git-send-email-normalperson@yhbt.net>

On Sun, May 14, 2006 at 07:13:44PM -0700, Eric Wong wrote:
> mutt, gnus, pine, mailrc formats should be supported.
> 
> Testing and feedback for correctness and completeness of all formats
> and support for additional formats would be good.
> 
> Nested expansions are also supported.
> 
> More than one alias file to be used.
> 
> All alias file formats must still of be the same type, though.
> 
> Two git repo-config keys are required for this
> (as suggested by Ryan Anderson):
> 
>     sendemail.aliasesfile = <filename of aliases file>
>     sendemail.aliasfiletype = (mutt|gnus|pine|mailrc)
> 
> Signed-off-by: Eric Wong <normalperson@yhbt.net>
Acked-by: Ryan Anderson <ryan@michonline.com>

> ---
> 
> Looks like this patch got forgotten a while ago, and I never noticed
> because I forgot to set WITH_SEND_EMAIL when doing make install.
> Of course, WITH_SEND_EMAIL should no longer be needed...
> 
>  git-send-email.perl |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 48 insertions(+), 0 deletions(-)
> 
> ff6593287dc500853c1cf05bdb0f32f970f10c9d
> diff --git a/git-send-email.perl b/git-send-email.perl
> index 703dd1f..d8c4b1f 100755
> --- a/git-send-email.perl
> +++ b/git-send-email.perl
> @@ -89,6 +89,41 @@ sub gitvar_ident {
>  my ($author) = gitvar_ident('GIT_AUTHOR_IDENT');
>  my ($committer) = gitvar_ident('GIT_COMMITTER_IDENT');
>  
> +my %aliases;
> +chomp(my @alias_files = `git-repo-config --get-all sendemail.aliasesfile`);
> +chomp(my $aliasfiletype = `git-repo-config sendemail.aliasfiletype`);
> +my %parse_alias = (
> +	# multiline formats can be supported in the future
> +	mutt => sub { my $fh = shift; while (<$fh>) {
> +		if (/^alias\s+(\S+)\s+(.*)$/) {
> +			my ($alias, $addr) = ($1, $2);
> +			$addr =~ s/#.*$//; # mutt allows # comments
> +			 # commas delimit multiple addresses
> +			$aliases{$alias} = [ split(/\s*,\s*/, $addr) ];
> +		}}},
> +	mailrc => sub { my $fh = shift; while (<$fh>) {
> +		if (/^alias\s+(\S+)\s+(.*)$/) {
> +			# spaces delimit multiple addresses
> +			$aliases{$1} = [ split(/\s+/, $2) ];
> +		}}},
> +	pine => sub { my $fh = shift; while (<$fh>) {
> +		if (/^(\S+)\s+(.*)$/) {
> +			$aliases{$1} = [ split(/\s*,\s*/, $2) ];
> +		}}},
> +	gnus => sub { my $fh = shift; while (<$fh>) {
> +		if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) {
> +			$aliases{$1} = [ $2 ];
> +		}}}
> +);
> +
> +if (@alias_files && defined $parse_alias{$aliasfiletype}) {
> +	foreach my $file (@alias_files) {
> +		open my $fh, '<', $file or die "opening $file: $!\n";
> +		$parse_alias{$aliasfiletype}->($fh);
> +		close $fh;
> +	}
> +}
> +
>  my $prompting = 0;
>  if (!defined $from) {
>  	$from = $author || $committer;
> @@ -112,6 +147,19 @@ if (!@to) {
>  	$prompting++;
>  }
>  
> +sub expand_aliases {
> +	my @cur = @_;
> +	my @last;
> +	do {
> +		@last = @cur;
> +		@cur = map { $aliases{$_} ? @{$aliases{$_}} : $_ } @last;
> +	} while (join(',',@cur) ne join(',',@last));
> +	return @cur;
> +}
> +
> +@to = expand_aliases(@to);
> +@initial_cc = expand_aliases(@initial_cc);
> +
>  if (!defined $initial_subject && $compose) {
>  	do {
>  		$_ = $term->readline("What subject should the emails start with? ",
> -- 
> 1.3.2.g1c9b
> 
> 

^ permalink raw reply

* Re: git diff: support "-U" and "--unified" options properly
From: Linus Torvalds @ 2006-05-15  3:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605141745410.3866@g5.osdl.org>



On Sun, 14 May 2006, Linus Torvalds wrote:
> 
> So I would actually assume that the solution is to simply make 
> grep_cache() have a simple
> 
> 	#ifdef __unix__
> 		if (!cached) {
> 			hit = external_grep(opt, paths, cached);
> 			if (hit >= 0)
> 				return hit;
> 		}
> 	#endif
> 
> at the top, so that we'd have the best of both worlds.

Ok. Here's a slightly tested version, my out-lined thing from the email 
was pretty close to working already.

It's not perfect, but it gets the "git grep some-random-string" down to 
the good old half-a-second range for the kernel.

It should convert more of the argument flags for "grep", that should be 
trivial to expand (I did a few just as an example). It should also bother 
to try to return the right "hit" value (which it doesn't, right now - the 
code is kind of there, but I didn't actually bother to do it _right_).

Also, right now it _just_ limits by number of arguments, but it should 
also strictly speaking limit by total argument size (ie add up the length 
of the filenames, and do the "exec_grep()" flush call if it's bigger than 
some random value like 32kB).

But I think that it's _conceptually_ doing all the right things, and it 
seems to work. So maybe somebody else can do some of the final polish.

		Linus

----
diff --git a/builtin-grep.c b/builtin-grep.c
index fead356..14471db 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -12,6 +12,7 @@ #include "tree-walk.h"
 #include "builtin.h"
 #include <regex.h>
 #include <fnmatch.h>
+#include <sys/wait.h>
 
 /*
  * git grep pathspecs are somewhat different from diff-tree pathspecs;
@@ -409,12 +410,90 @@ static int grep_file(struct grep_opt *op
 	return i;
 }
 
+static int exec_grep(int argc, const char **argv)
+{
+	pid_t pid;
+	int status;
+
+	argv[argc] = NULL;
+	pid = fork();
+	if (pid < 0)
+		return pid;
+	if (!pid) {
+		execvp("grep", (char **) argv);
+		exit(255);
+	}
+	while (waitpid(pid, &status, 0) < 0) {
+		if (errno == EINTR)
+			continue;
+		return -1;
+	}
+	if (WIFEXITED(status)) {
+		if (!WEXITSTATUS(status))
+			return 1;
+		return 0;
+	}
+	return -1;
+}
+
+#define MAXARGS 1000
+
+static int external_grep(struct grep_opt *opt, const char **paths, int cached)
+{
+	int i, nr, argc, hit;
+	const char *argv[MAXARGS+1];
+	struct grep_pat *p;
+
+	nr = 0;
+	argv[nr++] = "grep";
+	if (opt->word_regexp)
+		argv[nr++] = "-w";
+	if (opt->name_only)
+		argv[nr++] = "-l";
+	for (p = opt->pattern_list; p; p = p->next) {
+		argv[nr++] = "-e";
+		argv[nr++] = p->pattern;
+	}
+	argv[nr++] = "--";
+
+	hit = 0;
+	argc = nr;
+	for (i = 0; i < active_nr; i++) {
+		struct cache_entry *ce = active_cache[i];
+		if (ce_stage(ce) || !S_ISREG(ntohl(ce->ce_mode)))
+			continue;
+		if (!pathspec_matches(paths, ce->name))
+			continue;
+		argv[argc++] = ce->name;
+		if (argc < MAXARGS)
+			continue;
+		hit += exec_grep(argc, argv);
+		argc = nr;
+	}
+	if (argc > nr)
+		hit += exec_grep(argc, argv);
+	return 0;
+}
+
 static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
 {
 	int hit = 0;
 	int nr;
 	read_cache();
 
+#ifdef __unix__
+	/*
+	 * Use the external "grep" command for the case where
+	 * we grep through the checked-out files. It tends to
+	 * be a lot more optimized
+	 */
+	if (!cached) {
+		hit = external_grep(opt, paths, cached);
+		if (hit >= 0)
+			return hit;
+	}
+#endif
+
 	for (nr = 0; nr < active_nr; nr++) {
 		struct cache_entry *ce = active_cache[nr];
 		if (ce_stage(ce) || !S_ISREG(ntohl(ce->ce_mode)))

^ permalink raw reply related

* Re: Tracking branch history
From: Shawn Pearce @ 2006-05-15  3:15 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vk68o19n4.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> wrote:
> Shawn Pearce <spearce@spearce.org> writes:
> 
> > Log ref updates to logs/refs/<ref>
> >
> > If config parameter core.logRefUpdates is true then append a line
> > to .git/logs/refs/<ref> whenever git-update-ref <ref> is executed.
> 
> I cannot decide if a parameter makes more sense, or just making
> the existence of such a file a cue is better.  For example, I do
> not much care about when I updated each of my topic branch head,
> while I do care about master, next, and pu branches.  A global
> parameter would make this black-or-white choice, while opening
> the log without O_CREAT and write things out only when the log
> file exists might make things as easy and controllable.
> 
> I could "touch" the ones I care about to prime the process.

I'm as torn as you are on this.  My `pg' would have some serious
issues with update-ref and the logRefUpdates config being true as it
uses a large number of refs to track the patch stack.  StGIT might
also be in a somewhat similiar position, but I think it uses slightly
less refs.  Opening without O_CREAT and letting the user touch the
log file into existance would fix this problem for most users.

But I can also see the case where the user has most branches logged
then infrequently creates a new branch but expects that branch
to also be logged.  What happens when they later find out its not
logging but they were counting on that log data to be there?

Perhaps a mix of the two solutions is ideal.  Use O_CREAT if
logRefUpdates is true and otherwise log only if the file already
exists.  This is now in the patch below.

I have also added an optional '-m <reason>' flag to update-ref,
for use in e.g. git-commit.  I have also moved the logging code to
refs.c where it could be used by fetch or upload-pack, but those
changes are not yet included in this patch.

--> -
Log ref updates to logs/refs/<ref>

If config parameter core.logAllRefUpdates is true or the log
file already exists then append a line to ".git/logs/refs/<ref>"
whenever git-update-ref <ref> is executed.  Each log line contains
the following information:

  oldsha1 <SP> newsha1 <SP> committer <LF>

where committer is the current user, date, time and timezone in
the standard GIT ident format.  If the caller is unable to append
to the log file then git-update-ref will fail without updating <ref>.

An optional message may be included in the log line with the -m flag.

---

 Documentation/config.txt         |    8 ++++++
 Documentation/git-update-ref.txt |   28 +++++++++++++++++++-
 cache.h                          |    1 +
 config.c                         |    5 ++++
 environment.c                    |    1 +
 refs.c                           |   50 ++++++++++++++++++++++++++++++++++++
 refs.h                           |    3 ++
 update-ref.c                     |   53 ++++++++++++++++++++++++++++++++------
 8 files changed, 139 insertions(+), 10 deletions(-)

bbac000fbc779c7434d66b10639eaa5ea218f62e
diff --git a/Documentation/config.txt b/Documentation/config.txt
index d1a4bec..e178ee2 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -70,6 +70,14 @@ core.preferSymlinkRefs::
 	This is sometimes needed to work with old scripts that
 	expect HEAD to be a symbolic link.
 
+core.logAllRefUpdates::
+	If true, `git-update-ref` will append a line to
+	"$GIT_DIR/logs/<ref>" listing the new SHA1 and the date/time
+	of the update.	If the file does not exist it will be
+	created automatically.	This information can be used to
+	determine what commit was the tip of a branch "2 days ago".
+	This value is false by default (no logging).
+
 core.repositoryFormatVersion::
 	Internal variable identifying the repository format and layout
 	version.
diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 475237f..dfbd886 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>]
+'git-update-ref' <ref> <newvalue> [<oldvalue>] [-m <reason>]
 
 DESCRIPTION
 -----------
@@ -49,6 +49,32 @@ for reading but not for writing (so we'l
 ref symlink to some other tree, if you have copied a whole
 archive by creating a symlink tree).
 
+Logging Updates
+---------------
+If config parameter "core.logAllRefUpdates" is true or the file
+"$GIT_DIR/logs/<ref>" exists then `git-update-ref` will append
+a line to the log file "$GIT_DIR/logs/<ref>" (dereferencing all
+symbolic refs before creating the log name) describing the change
+in ref value.  Log lines are formatted as:
+
+    . oldsha1 SP newsha1 SP committer LF
++
+Where "oldsha1" is the 40 character hexadecimal value previously
+stored in <ref>, "newsha1" is the 40 character hexadecimal value of
+<newvalue> and "committer" is the committer's name, email address
+and date in the standard GIT committer ident format.
+
+Optionally with -m:
+
+    . oldsha1 SP newsha1 SP committer TAB message LF
++
+Where all fields are as described above and "message" is the
+value supplied to the -m option.
+
+An update will fail (without changing <ref>) if the current user is
+unable to create a new log file, append to the existing log file
+or does not have committer information available.
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>.
diff --git a/cache.h b/cache.h
index b1300cd..82adbba 100644
--- a/cache.h
+++ b/cache.h
@@ -171,6 +171,7 @@ extern void rollback_index_file(struct c
 extern int trust_executable_bit;
 extern int assume_unchanged;
 extern int prefer_symlink_refs;
+extern int log_all_ref_updates;
 extern int warn_ambiguous_refs;
 extern int diff_rename_limit_default;
 extern int shared_repository;
diff --git a/config.c b/config.c
index 0f518c9..fa6db4b 100644
--- a/config.c
+++ b/config.c
@@ -232,6 +232,11 @@ int git_default_config(const char *var, 
 		return 0;
 	}
 
+	if (!strcmp(var, "core.logallrefupdates")) {
+		log_all_ref_updates = git_config_bool(var, value);
+		return 0;
+	}
+
 	if (!strcmp(var, "core.warnambiguousrefs")) {
 		warn_ambiguous_refs = git_config_bool(var, value);
 		return 0;
diff --git a/environment.c b/environment.c
index 444c99e..2e79eab 100644
--- a/environment.c
+++ b/environment.c
@@ -14,6 +14,7 @@ char git_default_name[MAX_GITNAME];
 int trust_executable_bit = 1;
 int assume_unchanged = 0;
 int prefer_symlink_refs = 0;
+int log_all_ref_updates = 0;
 int warn_ambiguous_refs = 1;
 int repository_format_version = 0;
 char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
diff --git a/refs.c b/refs.c
index 275b914..691a8ba 100644
--- a/refs.c
+++ b/refs.c
@@ -375,3 +375,53 @@ int write_ref_sha1_unlocked(const char *
 	free(lock_filename);
 	return retval;
 }
+
+int log_ref_update(const char *ref, const unsigned char *currsha1, const unsigned char *newsha1, const char *msg)
+{
+	char *logpath, *logrec;
+	const char *comitter;
+	unsigned maxlen, len;
+	int oflags, logfd, written;
+
+	oflags = O_APPEND | O_WRONLY;
+	logpath = git_path("logs/%s", ref);
+	if (log_all_ref_updates) {
+		if (safe_create_leading_directories(logpath) < 0)
+			return error("Unable to create all of %s", logpath);
+		oflags |= O_CREAT;
+	}
+
+	logfd = open(logpath, oflags, 0666);
+	if (logfd < 0) {
+		if (!log_all_ref_updates && errno == ENOENT)
+			return 0;
+		return error("Unable to append to %s: %s", logpath, strerror(errno));
+	}
+
+	setup_ident();
+	comitter = git_committer_info(1);
+	if (msg) {
+		maxlen = strlen(comitter) + strlen(msg) + 2*40 + 5;
+		logrec = xmalloc(maxlen);
+		len = snprintf(logrec, maxlen, "%s %s %s\t%s\n",
+			sha1_to_hex(currsha1),
+			sha1_to_hex(newsha1),
+			comitter,
+			msg);
+	} else {
+		maxlen = strlen(comitter) + 2*40 + 4;
+		logrec = xmalloc(maxlen);
+		len = snprintf(logrec, maxlen, "%s %s %s\n",
+			sha1_to_hex(currsha1),
+			sha1_to_hex(newsha1),
+			comitter);
+	}
+	if (len >= maxlen)
+		return error("Internal error formatting log record.");
+	written = write(logfd, logrec, len);
+	if (written != len)
+		return error("Unable to append to %s", logpath);
+	free(logrec);
+	close(logfd);
+	return 0;
+}
diff --git a/refs.h b/refs.h
index 2625596..9345942 100644
--- a/refs.h
+++ b/refs.h
@@ -25,4 +25,7 @@ extern int write_ref_sha1_unlocked(const
 /** Returns 0 if target has the right format for a ref. **/
 extern int check_ref_format(const char *target);
 
+/** If logging is enabled logs the change made to the ref. **/
+extern int log_ref_update(const char *ref, const unsigned char *currsha1, const unsigned char *newsha1, const char *msg);
+
 #endif /* REFS_H */
diff --git a/update-ref.c b/update-ref.c
index fd48742..95940dd 100644
--- a/update-ref.c
+++ b/update-ref.c
@@ -1,7 +1,8 @@
 #include "cache.h"
 #include "refs.h"
 
-static const char git_update_ref_usage[] = "git-update-ref <refname> <value> [<oldval>]";
+static const char git_update_ref_usage[] =
+"git-update-ref <refname> <value> [<oldval>] [-m <reason>]";
 
 static int re_verify(const char *path, unsigned char *oldsha1, unsigned char *currsha1)
 {
@@ -19,26 +20,50 @@ static int re_verify(const char *path, u
 int main(int argc, char **argv)
 {
 	char *hex;
-	const char *refname, *value, *oldval, *path;
+	const char *refname=NULL, *value=NULL, *oldval=NULL, *msg=NULL, *path;
 	char *lockpath;
 	unsigned char sha1[20], oldsha1[20], currsha1[20];
-	int fd, written;
+	int i, fd, written, pfxlen;
 
 	setup_git_directory();
 	git_config(git_default_config);
-	if (argc < 3 || argc > 4)
+
+	for (i = 1; i < argc; i++) {
+		if (!strcmp("-m", argv[i])) {
+			if (i+1 >= argc)
+				usage(git_update_ref_usage);
+			msg = argv[++i];
+			if (!*msg)
+				die("Refusing to perform update with empty message.");
+			if (strchr(msg, '\n'))
+				die("Refusing to perform update with \\n in message.");
+			continue;
+		}
+		if (!refname) {
+			refname = argv[i];
+			continue;
+		}
+		if (!value) {
+			value = argv[i];
+			continue;
+		}
+		if (!oldval) {
+			oldval = argv[i];
+			continue;
+		}
+	}
+	if (!refname || !value)
 		usage(git_update_ref_usage);
 
-	refname = argv[1];
-	value = argv[2];
-	oldval = argv[3];
 	if (get_sha1(value, sha1))
 		die("%s: not a valid SHA1", value);
 	memset(oldsha1, 0, 20);
 	if (oldval && get_sha1(oldval, oldsha1))
 		die("%s: not a valid old SHA1", oldval);
 
-	path = resolve_ref(git_path("%s", refname), currsha1, !!oldval);
+	path = git_path("%s", refname);
+	pfxlen = strlen(path) - strlen(refname);
+	path = resolve_ref(path, currsha1, !!oldval);
 	if (!path)
 		die("No such ref: %s", refname);
 
@@ -49,8 +74,13 @@ int main(int argc, char **argv)
 		if (!memcmp(oldsha1, sha1, 20))
 			exit(0);
 	}
+
+	/* No change in ref.  Don't do anything. */
+	if (!memcmp(currsha1, sha1, 20))
+		exit(0);
+
 	path = strdup(path);
-	lockpath = mkpath("%s.lock", path);
+	lockpath = strdup(mkpath("%s.lock", path));
 	if (safe_create_leading_directories(lockpath) < 0)
 		die("Unable to create all of %s", lockpath);
 
@@ -74,6 +104,11 @@ int main(int argc, char **argv)
 		die("Ref lock failed");
 	}
 
+	if (log_ref_update(path + pfxlen, currsha1, sha1, msg) < 0) {
+		unlink(lockpath);
+		die("Logging ref update failed, update aborted.");
+	}
+
 	/*
 	 * Finally, replace the old ref with the new one
 	 */
-- 
1.3.2.g7278

^ permalink raw reply related

* [PATCH] send-email: quiet some warnings
From: Eric Wong @ 2006-05-15  2:38 UTC (permalink / raw)
  To: Junio C Hamano, git; +Cc: Eric Wong
In-Reply-To: <1147660345772-git-send-email-normalperson@yhbt.net>

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 git-send-email.perl |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

0e5a33f56f62e527b74b2afbd93a1cca812f97af
diff --git a/git-send-email.perl b/git-send-email.perl
index d27a7a5..379e0c4 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -507,8 +507,16 @@ sub unique_email_list(@) {
 	my @emails;
 
 	foreach my $entry (@_) {
-		my $clean = extract_valid_address($entry);
-		next if $seen{$clean}++;
+		if (my $clean = extract_valid_address($entry)) {
+			$seen{$clean} ||= 0;
+			next if $seen{$clean}++;
+		} else {
+			# it could still be a local email address without '@',
+			# which neither Email::Valid or our own small regex says
+			# is valid...
+			$seen{$entry} ||= 0;
+			next if $seen{$entry}++;
+		}
 		push @emails, $entry;
 	}
 	return @emails;
-- 
1.3.2.g0e5a

^ permalink raw reply related

* Re: [PATCH] Add "--summary" option to git diff.
From: Junio C Hamano @ 2006-05-15  2:34 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Sean, git, Johannes.Schindelin
In-Reply-To: <Pine.LNX.4.64.0605141848080.3866@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Sun, 14 May 2006, Sean wrote:
>> 
>> What's a bit more worrying is that:
>> 
>> $ PAGER= ./git whatchanged -B -C --stat --no-merges --diff-filter=RC
>> 
>> Causes the same problem on the current (1.3.2) release branch without any
>> other patches applied at all.

And the culprit was _me_ X-<.  *BLUSH*


-- >8 --

diff --git a/diff.c b/diff.c
index 7a7b839..2d72673 100644
--- a/diff.c
+++ b/diff.c
@@ -232,11 +232,16 @@ static char *pprint_rename(const char *a
 	 * name-a => name-b
 	 */
 	if (pfx_length + sfx_length) {
+		int a_len = len_a - pfx_length - sfx_length;
+		int b_len = len_b - pfx_length - sfx_length;
+		if (a_len < 0) a_len = 0;
+		if (b_len < 0) b_len = 0;
+
 		name = xmalloc(len_a + len_b - pfx_length - sfx_length + 7);
 		sprintf(name, "%.*s{%.*s => %.*s}%s",
 			pfx_length, a,
-			len_a - pfx_length - sfx_length, a + pfx_length,
-			len_b - pfx_length - sfx_length, b + pfx_length,
+			a_len, a + pfx_length,
+			b_len, b + pfx_length,
 			a + len_a - sfx_length);
 	}
 	else {

^ permalink raw reply related

* Re: [PATCH] send-email: allow sendmail binary to be used instead of SMTP
From: Eric Wong @ 2006-05-15  2:34 UTC (permalink / raw)
  To: git; +Cc: Martin Langhoff
In-Reply-To: <1147660345772-git-send-email-normalperson@yhbt.net>

Eric Wong <normalperson@yhbt.net> wrote:
> This should make local mailing possible for machines without
> a connection to an SMTP server.
> 
> It'll default to using /usr/sbin/sendmail or /usr/lib/sendmail
> if no SMTP server is specified (the default).  If it can't find
> either of those paths, it'll fall back to connecting to an SMTP
> server on localhost.
> 
> Signed-off-by: Eric Wong <normalperson@yhbt.net>

Also, Thanks to Martin Langhoff for bringing this up.

-- 
Eric Wong

^ permalink raw reply

* [PATCH] send-email: allow sendmail binary to be used instead of SMTP
From: Eric Wong @ 2006-05-15  2:32 UTC (permalink / raw)
  To: Junio C Hamano, git; +Cc: Eric Wong

This should make local mailing possible for machines without
a connection to an SMTP server.

It'll default to using /usr/sbin/sendmail or /usr/lib/sendmail
if no SMTP server is specified (the default).  If it can't find
either of those paths, it'll fall back to connecting to an SMTP
server on localhost.

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 git-send-email.perl |   55 +++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 42 insertions(+), 13 deletions(-)

1c9bacc5a2bfe382f68046aeba62302d28e4c976
diff --git a/git-send-email.perl b/git-send-email.perl
index d8c4b1f..d27a7a5 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -40,7 +40,8 @@ # Variables we fill in automatically, or
 my (@to,@cc,@initial_cc,$initial_reply_to,$initial_subject,@files,$from,$compose,$time);
 
 # Behavior modification variables
-my ($chain_reply_to, $smtp_server, $quiet, $suppress_from, $no_signed_off_cc) = (1, "localhost", 0, 0, 0);
+my ($chain_reply_to, $quiet, $suppress_from, $no_signed_off_cc) = (1, 0, 0, 0);
+my $smtp_server;
 
 # Example reply to:
 #$initial_reply_to = ''; #<20050203173208.GA23964@foobar.com>';
@@ -179,8 +180,14 @@ if (!defined $initial_reply_to && $promp
 	$initial_reply_to =~ s/(^\s+|\s+$)//g;
 }
 
-if (!defined $smtp_server) {
-	$smtp_server = "localhost";
+if (!$smtp_server) {
+	foreach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) {
+		if (-x $_) {
+			$smtp_server = $_;
+			last;
+		}
+	}
+	$smtp_server ||= 'localhost'; # could be 127.0.0.1, too... *shrug*
 }
 
 if ($compose) {
@@ -358,18 +365,39 @@ X-Mailer: git-send-email $gitversion
 ";
 	$header .= "In-Reply-To: $reply_to\n" if $reply_to;
 
-	$smtp ||= Net::SMTP->new( $smtp_server );
-	$smtp->mail( $from ) or die $smtp->message;
-	$smtp->to( @recipients ) or die $smtp->message;
-	$smtp->data or die $smtp->message;
-	$smtp->datasend("$header\n$message") or die $smtp->message;
-	$smtp->dataend() or die $smtp->message;
-	$smtp->ok or die "Failed to send $subject\n".$smtp->message;
+	if ($smtp_server =~ m#^/#) {
+		my $pid = open my $sm, '|-';
+		defined $pid or die $!;
+		if (!$pid) {
+			exec($smtp_server,'-i',@recipients) or die $!;
+		}
+		print $sm "$header\n$message";
+		close $sm or die $?;
+		if ($quiet) {
+			printf "Sent %s\n", $subject;
+		} else {
+			print "OK. Log says:
+Date: $date
+Sendmail: $smtp_server
+From: $from
+Subject: $subject
+Cc: $cc
+To: $to
 
-	if ($quiet) {
-		printf "Sent %s\n", $subject;
+Result: OK\n";
+		}
 	} else {
-		print "OK. Log says:
+		$smtp ||= Net::SMTP->new( $smtp_server );
+		$smtp->mail( $from ) or die $smtp->message;
+		$smtp->to( @recipients ) or die $smtp->message;
+		$smtp->data or die $smtp->message;
+		$smtp->datasend("$header\n$message") or die $smtp->message;
+		$smtp->dataend() or die $smtp->message;
+		$smtp->ok or die "Failed to send $subject\n".$smtp->message;
+		if ($quiet) {
+			printf "Sent %s\n", $subject;
+		} else {
+			print "OK. Log says:
 Date: $date
 Server: $smtp_server Port: 25
 From: $from
@@ -378,6 +406,7 @@ Cc: $cc
 To: $to
 
 Result: ", $smtp->code, ' ', ($smtp->message =~ /\n([^\n]+\n)$/s), "\n";
+		}
 	}
 }
 
-- 
1.3.2.g1c9b

^ permalink raw reply related

* [PATCH] Install git-send-email by default
From: Eric Wong @ 2006-05-15  2:26 UTC (permalink / raw)
  To: Junio C Hamano, git; +Cc: Eric Wong

After 567ffeb7722eefab3991cb894c96548b92b57cc2 and
4bc87a28be020a6bf7387161c65ea3d8e4a0228b, git-send-email no
longer requires any non-standard Perl modules, so there's no
reason to special-case it.

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 Makefile    |    7 ++-----
 git.spec.in |    4 ++--
 2 files changed, 4 insertions(+), 7 deletions(-)

df2d76fcee34efcf265b3a8a45940138e11a97c4
diff --git a/Makefile b/Makefile
index 8fd3e13..95d25f0 100644
--- a/Makefile
+++ b/Makefile
@@ -131,7 +131,8 @@ SCRIPT_PERL = \
 	git-archimport.perl git-cvsimport.perl git-relink.perl \
 	git-shortlog.perl git-fmt-merge-msg.perl git-rerere.perl \
 	git-annotate.perl git-cvsserver.perl \
-	git-svnimport.perl git-mv.perl git-cvsexportcommit.perl
+	git-svnimport.perl git-mv.perl git-cvsexportcommit.perl \
+	git-send-email.perl
 
 SCRIPT_PYTHON = \
 	git-merge-recursive.py
@@ -320,10 +321,6 @@ else
 	endif
 endif
 
-ifdef WITH_SEND_EMAIL
-	SCRIPT_PERL += git-send-email.perl
-endif
-
 ifndef NO_CURL
 	ifdef CURLDIR
 		# This is still problematic -- gcc does not always want -R.
diff --git a/git.spec.in b/git.spec.in
index 96dfc1d..8ccd256 100644
--- a/git.spec.in
+++ b/git.spec.in
@@ -74,12 +74,12 @@ Git revision tree visualiser ('gitk')
 %setup -q
 
 %build
-make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_OWN_SUBPROCESS_PY=YesPlease WITH_SEND_EMAIL=1 \
+make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_OWN_SUBPROCESS_PY=YesPlease \
      prefix=%{_prefix} all %{!?_without_docs: doc}
 
 %install
 rm -rf $RPM_BUILD_ROOT
-make %{_smp_mflags} DESTDIR=$RPM_BUILD_ROOT WITH_OWN_SUBPROCESS_PY=YesPlease WITH_SEND_EMAIL=1 \
+make %{_smp_mflags} DESTDIR=$RPM_BUILD_ROOT WITH_OWN_SUBPROCESS_PY=YesPlease \
      prefix=%{_prefix} mandir=%{_mandir} \
      install %{!?_without_docs: install-doc}
 
-- 
1.3.2.g1c9b

^ permalink raw reply related

* [PATCH (resend)] send-email: address expansion for common mailers
From: Eric Wong @ 2006-05-15  2:13 UTC (permalink / raw)
  To: Junio C Hamano, git, Ryan Anderson; +Cc: Eric Wong
In-Reply-To: <20060326024416.GA14234@localdomain>

mutt, gnus, pine, mailrc formats should be supported.

Testing and feedback for correctness and completeness of all formats
and support for additional formats would be good.

Nested expansions are also supported.

More than one alias file to be used.

All alias file formats must still of be the same type, though.

Two git repo-config keys are required for this
(as suggested by Ryan Anderson):

    sendemail.aliasesfile = <filename of aliases file>
    sendemail.aliasfiletype = (mutt|gnus|pine|mailrc)

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

Looks like this patch got forgotten a while ago, and I never noticed
because I forgot to set WITH_SEND_EMAIL when doing make install.
Of course, WITH_SEND_EMAIL should no longer be needed...

 git-send-email.perl |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)

ff6593287dc500853c1cf05bdb0f32f970f10c9d
diff --git a/git-send-email.perl b/git-send-email.perl
index 703dd1f..d8c4b1f 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -89,6 +89,41 @@ sub gitvar_ident {
 my ($author) = gitvar_ident('GIT_AUTHOR_IDENT');
 my ($committer) = gitvar_ident('GIT_COMMITTER_IDENT');
 
+my %aliases;
+chomp(my @alias_files = `git-repo-config --get-all sendemail.aliasesfile`);
+chomp(my $aliasfiletype = `git-repo-config sendemail.aliasfiletype`);
+my %parse_alias = (
+	# multiline formats can be supported in the future
+	mutt => sub { my $fh = shift; while (<$fh>) {
+		if (/^alias\s+(\S+)\s+(.*)$/) {
+			my ($alias, $addr) = ($1, $2);
+			$addr =~ s/#.*$//; # mutt allows # comments
+			 # commas delimit multiple addresses
+			$aliases{$alias} = [ split(/\s*,\s*/, $addr) ];
+		}}},
+	mailrc => sub { my $fh = shift; while (<$fh>) {
+		if (/^alias\s+(\S+)\s+(.*)$/) {
+			# spaces delimit multiple addresses
+			$aliases{$1} = [ split(/\s+/, $2) ];
+		}}},
+	pine => sub { my $fh = shift; while (<$fh>) {
+		if (/^(\S+)\s+(.*)$/) {
+			$aliases{$1} = [ split(/\s*,\s*/, $2) ];
+		}}},
+	gnus => sub { my $fh = shift; while (<$fh>) {
+		if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) {
+			$aliases{$1} = [ $2 ];
+		}}}
+);
+
+if (@alias_files && defined $parse_alias{$aliasfiletype}) {
+	foreach my $file (@alias_files) {
+		open my $fh, '<', $file or die "opening $file: $!\n";
+		$parse_alias{$aliasfiletype}->($fh);
+		close $fh;
+	}
+}
+
 my $prompting = 0;
 if (!defined $from) {
 	$from = $author || $committer;
@@ -112,6 +147,19 @@ if (!@to) {
 	$prompting++;
 }
 
+sub expand_aliases {
+	my @cur = @_;
+	my @last;
+	do {
+		@last = @cur;
+		@cur = map { $aliases{$_} ? @{$aliases{$_}} : $_ } @last;
+	} while (join(',',@cur) ne join(',',@last));
+	return @cur;
+}
+
+@to = expand_aliases(@to);
+@initial_cc = expand_aliases(@initial_cc);
+
 if (!defined $initial_subject && $compose) {
 	do {
 		$_ = $term->readline("What subject should the emails start with? ",
-- 
1.3.2.g1c9b

^ permalink raw reply related

* Re: Branch relationships
From: Junio C Hamano @ 2006-05-15  2:11 UTC (permalink / raw)
  To: Josef Weidendorfer; +Cc: git
In-Reply-To: <200605150348.53879.Josef.Weidendorfer@gmx.de>

Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:

> But not supporting this in a first step should be no problem, as
> you always can do "git pull somewhere that-head" directly.

That defeats the point of .git/remotes/ setup, and I suspect is
unacceptable to people who pull from a given branch of a given
repository repeatedly without ever tracking it.  Think of the
maintainer pulling from subsystem maintainers.

^ permalink raw reply

* Re: [PATCH] Add "--summary" option to git diff.
From: Linus Torvalds @ 2006-05-15  1:51 UTC (permalink / raw)
  To: Sean; +Cc: Junio C Hamano, git, Johannes.Schindelin
In-Reply-To: <BAYC1-PASMTP02640E2C9813E4DA1E778BAEA30@CEZ.ICE>



On Sun, 14 May 2006, Sean wrote:
> 
> What's a bit more worrying is that:
> 
> $ PAGER= ./git whatchanged -B -C --stat --no-merges --diff-filter=RC
> 
> Causes the same problem on the current (1.3.2) release branch without any
> other patches applied at all.

If you have electric fence installed, just do

	PAGER= ef ./git whatchanged -B -C --stat --no-merges --diff-filter=RC

to run it with the efence preload, which should cause a core-dump and/or 
be more debuggable.

Sadly, last I tried, you can't run gdb under ef, because electric fence 
(incorrectly) thinks that zero-size allocations are bad.

		Linus
	

^ permalink raw reply

* Re: git diff: support "-U" and "--unified" options properly
From: Junio C Hamano @ 2006-05-15  1:51 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605141745410.3866@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Sun, 14 May 2006, Junio C Hamano wrote:
>> 
>> I am not either after seeing your numbers and trying them
>> myself.  I was going to look at it myself over the weekend, but
>> I ended up spending most of the time migrating my environment,
>> so no progress on that front yet.  Sorry.
>
> I was looking at it, and I just suspect that "grep" is very optimized.
>
> At the same time, the built-in one had many good features, notably that 
> you could grep the cached copy and from a specific version. So I think it 
> makes sense.
> 
> ... Except for testing, and fixing my stupid bugs, which 
> I'm too lazy to do.

The command line flags needs to be
unparsed before feeding the external grep.

> The whole "exec_grep()" should basically be the same as "spawn_prog()". 
> You get the idea.
>
> Anybody?

I think somebody wanted to have his own funky grep spawned off
from his PATH, so I'd leave that to him (or her I do not
remember which) ;-).

^ permalink raw reply

* Re: Branch relationships
From: Josef Weidendorfer @ 2006-05-15  1:48 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vslncyxez.fsf@assigned-by-dhcp.cox.net>

On Monday 15 May 2006 01:55, you wrote:
> > After a "git clone", we would have
> >
> >  [remote "origin"]
> >    url = ...
> >    fetch = master:origin
> >
> >  [branch "master"]
> >    origin = "origin" ; upstream of master is local branch "origin"
> 
> Doesn't that arrangement force people to use tracking branches?

I think we already had the same discussion some time ago ;-)
This asks for support of a way to specify a remote origin branch
without any local tracking, like
  origin = "<remotebranch> of <remote>"

But not supporting this in a first step should be no problem, as
you always can do "git pull somewhere that-head" directly.

A side-effect of the origin-arrangement would be that branching
off a tracking branch would automatically update it on pull from
the new branch. I would see this as improvement of usability as
"generating a local development branch from a remote one" does
not need any special command.

^ permalink raw reply

* Re: [PATCH] Add "--summary" option to git diff.
From: Sean @ 2006-05-15  0:54 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Johannes.Schindelin
In-Reply-To: <7v3bfcno2b.fsf@assigned-by-dhcp.cox.net>

On Sun, 14 May 2006 17:12:28 -0700
Junio C Hamano <junkio@cox.net> wrote:

> The next branch with this and other patches applied seems to
> misbehave.
> 
> It makes glibc unhappy with 
> 
> PAGER= ./git whatchanged -B -C --stat --summary --no-merges --diff-filter=RC

What's a bit more worrying is that:

$ PAGER= ./git whatchanged -B -C --stat --no-merges --diff-filter=RC

Causes the same problem on the current (1.3.2) release branch without any
other patches applied at all.

Sean

^ permalink raw reply

* Re: git diff: support "-U" and "--unified" options properly
From: Linus Torvalds @ 2006-05-15  0:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vbqu0yvda.fsf@assigned-by-dhcp.cox.net>



On Sun, 14 May 2006, Junio C Hamano wrote:
> 
> I am not either after seeing your numbers and trying them
> myself.  I was going to look at it myself over the weekend, but
> I ended up spending most of the time migrating my environment,
> so no progress on that front yet.  Sorry.

I was looking at it, and I just suspect that "grep" is very optimized.

At the same time, the built-in one had many good features, notably that 
you could grep the cached copy and from a specific version. So I think it 
makes sense.

I have this suspicion that the best solution is to just handle the "grep 
against current tree" separately, and even make that something that only 
gets enabled on UNIX - I assume that trying to execve() grep externally 
would suck on windows again.

So I would actually assume that the solution is to simply make 
grep_cache() have a simple

	#ifdef __unix__
		if (!cached) {
			hit = external_grep(opt, paths, cached);
			if (hit >= 0)
				return hit;
		}
	#endif

at the top, so that we'd have the best of both worlds.

The "external_grep()" should look something like this:

	#define MAXARGS 1000

	static int external_grep(struct grep_opt *opt, const char **paths, int cached)
	{
		int nr;
		char *argv[MAXARGS];

		read_cache();
		argv[0] = "grep";
		argv[1] = "-e";
		argv[2] = opt->pattern;	/* whatever */
		argv[3] = "--";
		argc = 4;

		for (nr = 0; nr < active_nr; nr++) {
			struct cache_entry *ce = active_cache[nr];
			if (ce_stage(ce) || !S_ISREG(ntohl(ce->ce_mode)))
				continue;
			if (!pathspec_matches(paths, ce->name))
				continue;
			argv[argc++] = ce->name;
			if (argc < MAXARGS)
				continue;
			hit += exec_grep(argv, argc);
			argc = 4;
		}
		if (argc > 4)
			hit += exec_grep(argv, argc);
		return hit;
	}

and you're all done. Except for testing, and fixing my stupid bugs, which 
I'm too lazy to do.

The whole "exec_grep()" should basically be the same as "spawn_prog()". 
You get the idea.

Anybody?

		Linus

^ permalink raw reply

* Re: git diff: support "-U" and "--unified" options properly
From: Junio C Hamano @ 2006-05-15  0:39 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605131518390.3866@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Sat, 13 May 2006, Junio C Hamano wrote:
>> 
>>  * built-in grep (jc/grep)
>> 
>>    Ready.
>
> I'm not entirely convinced.

I am not either after seeing your numbers and trying them
myself.  I was going to look at it myself over the weekend, but
I ended up spending most of the time migrating my environment,
so no progress on that front yet.  Sorry.



^ permalink raw reply

* [PATCH] commit: allow --pretty= args to be abbreviated
From: Eric Wong @ 2006-05-15  0:34 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vwtcoyxs2.fsf@assigned-by-dhcp.cox.net>

Unlike the original one, this one only does prefix matches, so
you can't do --pretty=er anymore :)

This one really works with and without the gitopt changes.

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

Junio C Hamano <junkio@cox.net> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
> 
> >  commit.c |   42 +++++++++++++++++++++++++++++-------------
> >  1 files changed, 29 insertions(+), 13 deletions(-)
> 
> This is applicable without the gitopt changes, but I have a
> feeling that when we think about abbreviations the users would
> expect the leading substring abbreviation, not strstr().
> 
> While "git log --pretty=lle" or "git log --pretty=or" might be
> unambiguous, I think that is trying to be too cute and
> confusing, especially if somebody picks up that habit by
> watching others type such a cute abbreviations.
> 
> That comment probably incidentally applies to your bigger
> patches.

Ok.  The current gitopt patch only uses leading substring abbreviations
by default.  GIT_ABBREV_HARDER needs to be set if you want all the
crazyness :)

 commit.c |   50 ++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 36 insertions(+), 14 deletions(-)

d4473559924b1a5ba655cd5d5b18d39f53e25184
diff --git a/commit.c b/commit.c
index 2717dd8..2753677 100644
--- a/commit.c
+++ b/commit.c
@@ -22,23 +22,45 @@ struct sort_node
 
 const char *commit_type = "commit";
 
+struct cmt_fmt_map {
+	const char *n;
+	enum cmit_fmt v;
+} cmt_fmts[] = {
+	{ "raw",	CMIT_FMT_RAW },
+	{ "medium",	CMIT_FMT_MEDIUM },
+	{ "short",	CMIT_FMT_SHORT },
+	{ "full",	CMIT_FMT_FULL },
+	{ "fuller",	CMIT_FMT_FULLER },
+	{ "oneline",	CMIT_FMT_ONELINE },
+};
+
 enum cmit_fmt get_commit_format(const char *arg)
 {
-	if (!*arg)
+	int i, found;
+	size_t len;
+
+	if (!arg || !*arg)
 		return CMIT_FMT_DEFAULT;
-	if (!strcmp(arg, "=raw"))
-		return CMIT_FMT_RAW;
-	if (!strcmp(arg, "=medium"))
-		return CMIT_FMT_MEDIUM;
-	if (!strcmp(arg, "=short"))
-		return CMIT_FMT_SHORT;
-	if (!strcmp(arg, "=full"))
-		return CMIT_FMT_FULL;
-	if (!strcmp(arg, "=fuller"))
-		return CMIT_FMT_FULLER;
-	if (!strcmp(arg, "=oneline"))
-		return CMIT_FMT_ONELINE;
-	die("invalid --pretty format");
+	if (*arg == '=')
+		arg++;
+	for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) {
+		if (!strcmp(arg, cmt_fmts[i].n))
+			return cmt_fmts[i].v;
+	}
+
+	/* look for abbreviations */
+	len = strlen(arg);
+	found = -1;
+	for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) {
+		if (!strncmp(cmt_fmts[i].n, arg, len)) {
+			if (found >= 0)
+				die("invalid --pretty format: %s", arg);
+			found = i;
+		}
+	}
+	if (found >= 0)
+		return cmt_fmts[found].v;
+	die("invalid --pretty format: %s", arg);
 }
 
 static struct commit *check_commit(struct object *obj,
-- 
1.3.2.g58c0

^ permalink raw reply related

* Re: [PATCH] Add "--branches", "--tags" and "--remotes" options to git-rev-parse.
From: Sean @ 2006-05-15  0:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8xp4196e.fsf@assigned-by-dhcp.cox.net>

On Sun, 14 May 2006 16:24:57 -0700
Junio C Hamano <junkio@cox.net> wrote:

> I do not have problem with that, but somebody else's script
> might; Cogito seems not to mind.
> 
> Something like this perhaps?

That looks good.  If you accept the rev-parse patch, then i'd suggest the
patch below instead.

Sean


diff --git a/git-tag.sh b/git-tag.sh
index dc6aa95..a0afa25 100755
--- a/git-tag.sh
+++ b/git-tag.sh
@@ -25,14 +25,12 @@ do
 	force=1
 	;;
     -l)
-        cd "$GIT_DIR/refs" &&
 	case "$#" in
 	1)
-		find tags -type f -print ;;
-	*)
-		shift
-		find tags -type f -print | grep "$@" ;;
+		set x . ;;
 	esac
+	shift
+	git rev-parse --symbolic --tags | sort | grep "$@"
 	exit $?
 	;;
     -m)

^ permalink raw reply related

* Re: [PATCH] Add "--summary" option to git diff.
From: Junio C Hamano @ 2006-05-15  0:12 UTC (permalink / raw)
  To: Sean; +Cc: git, Johannes Schindelin
In-Reply-To: <BAYC1-PASMTP0770FC4238970CB812C192AEA20@CEZ.ICE>

Sean <seanlkml@sympatico.ca> writes:

> Remove the need to pipe git diff through git apply to
> get the extended headers summary.
>
> Signed-off-by: Sean Estabrooks <seanlkml@sympatico.ca>

Hmph...

The next branch with this and other patches applied seems to
misbehave.

It makes glibc unhappy with 

PAGER= ./git whatchanged -B -C --stat --summary --no-merges --diff-filter=RC

and "*** glibc detected *** malloc(): memory corruption: xxx ***"

but not with this:

PAGER= ./git whatchanged -B -C --no-merges --diff-filter=RC

nor with this:

PAGER= ./git whatchanged -B -C --summary --no-merges --diff-filter=RC

works just fine, so this is _not_ your fault, and I know who to
harrass ;-).

^ permalink raw reply

* Re: Branch relationships
From: Junio C Hamano @ 2006-05-14 23:55 UTC (permalink / raw)
  To: Josef Weidendorfer; +Cc: git
In-Reply-To: <200605150104.46762.Josef.Weidendorfer@gmx.de>

Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:

> On Monday 15 May 2006 00:19, you wrote:
>> > I suppose "branch.<branch name>.origin" is still the way to go for
>> > specifying the upstream?
>> 
>> Probably "origin" is a better name for it; I was assuming
>> "branch.<branch name>.remote = foo" refers to a [remote "foo"]
>> section and means "when on this branch, pull from foo and merge
>> from it".
>
> Maybe.
>
> But there is a misunderstanding. I wanted the branch attribute "origin"
> to specify the upstream _branch_, not a remote.
>
> After a "git clone", we would have
>
>  [remote "origin"]
>    url = ...
>    fetch = master:origin
>
>  [branch "master"]
>    origin = "origin" ; upstream of master is local branch "origin"

Doesn't that arrangement force people to use tracking branches?
IOW, "git pull somewhere that-head" fetches that-head, without
storing it anywhere in the local repository as a tracking
branch, and immediately merges it to the current branch.

^ permalink raw reply

* Re: [PATCH 4/5] commit: allow --pretty= args to be abbreviated
From: Junio C Hamano @ 2006-05-14 23:47 UTC (permalink / raw)
  To: Eric Wong; +Cc: git
In-Reply-To: <1147619963765-git-send-email-normalperson@yhbt.net>

Eric Wong <normalperson@yhbt.net> writes:

>  commit.c |   42 +++++++++++++++++++++++++++++-------------
>  1 files changed, 29 insertions(+), 13 deletions(-)

This is applicable without the gitopt changes, but I have a
feeling that when we think about abbreviations the users would
expect the leading substring abbreviation, not strstr().

While "git log --pretty=lle" or "git log --pretty=or" might be
unambiguous, I think that is trying to be too cute and
confusing, especially if somebody picks up that habit by
watching others type such a cute abbreviations.

That comment probably incidentally applies to your bigger
patches.

^ permalink raw reply

* Re: [PATCH 5/5] diff: parse U/u/unified options with an optional integer arg
From: Eric Wong @ 2006-05-14 23:36 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605140931410.3866@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> wrote:
> 
> 
> On Sun, 14 May 2006, Eric Wong wrote:
> > 
> > -u (lowercase) now accepts an optional arg, like -U (GNU diff
> > -u also has this behavior).
> 
> Actually, modern GNU "diff -u5" will say
> 
> 	diff: `-5' option is obsolete; use `-U 5'
> 	diff: Try `diff --help' for more information.
> 
> and exit.
> 
> I'm not entirely sure why, but I think it's because "u" can be mixed (ie 
> with something like "-urN"), while "U" cannot. The GNU diff rule seems to 
> be that simple arguments can be mixed together, but arguments with 
> parameters cannot. Which sounds sane.

Interesting.  With _POSIX2_VERSION < 200112, diff is happy to accept
-u5.  Setting _POSIX2_VERSION >= 200112 causes it to burp, however.

It turns out -u5 is actually short for -u -5, but I (and apparently some
other people) have always assumed -u5 worked like -U5.  POSIX doesn't
like -<num> switches, however, but we support it regardless in rev-list.

I prefer that it works the -u5 way, of course :)

Also, I find integer arguments being bundled with other parameters to be
pretty nice feature, but it's easy to disable if users don't like it:

diff --git a/gitopt.c b/gitopt.c
index 9e85247..139cd2d 100644
--- a/gitopt.c
+++ b/gitopt.c
@@ -270,17 +270,9 @@ static const char * parse_bundled(struct
        } else if (s->arg_fl) {
                if (*cur) {
                        /* no space between the arg and opt switch: */
-                       if (s->arg_fl & ARG_IS_INT) {
-                               /* we know to handle stuff like:
-                                * -h24w80 => -h=24 -w=80 */
-                               char *endptr = (char *)cur;
-                               strtol(cur, &endptr, 10);
-
-                               while (cur < endptr)
-                                       *c++ = *cur++;
-                       } else if (s->arg_fl & ARG_ONE) {
-                               /* unfortunately, other args are less
-                                * clear-cut */
+                       if (s->arg_fl & ARG_ONE) {
+                               /* don't attempt further unbundling, extra
+                                * chars are arguments */
                                while (*cur)
                                        *c++ = *cur++;
                        }

-- 
Eric Wong

^ 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