Re: [PATCH] cvsimport move over to using git for each ref to read refs

3 messages, 2 authors, 2016-06-15 · open the first message on its own page

Re: [PATCH] cvsimport move over to using git for each ref to read refs

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:41

Andy Whitcroft [off-list ref] writes:
I guess we could teach for-each-ref to output this as well?  Perhaps
something like authorstamp?
I think you can work with "author" or "committer" to grab the
whole raw line.

About the quoting and parsing, language specific quoting mode is
meant for git-for-each-ref to produce a string that can be eval'ed
in the host language.  Think of the command as a tool to write a
short program for you.

The original is like this:

	# Get the last import timestamps
	opendir(D,"$git_dir/refs/heads");
	while(defined(my $head = readdir(D))) {
		next if $head =~ /^\./;
		open(F,"$git_dir/refs/heads/$head")
			or die "Bad head branch: $head: $!\n";
		chomp(my $ftag = <F>);
		close(F);
		open(F,"git-cat-file commit $ftag |");
		while(<F>) {
			next unless /^author\s.*\s(\d+)\s[-+]\d{4}$/;
			$branch_date{$head} = $1;
			last;
		}
		close(F);
	}
	closedir(D);

The purpose of the loop is to grab all branch heads, and grab
author timestamp for all of them, _and_ stash that in
%branch_date hash indexed by head name.  You would want to have
something like this executed for each branch:

	$refname = %(refname);
	$authorline = %(author);
	$authorline =~ /^author\s.*\s(\d+)\s[-+]\d{4}$/;
        $branch_date{$refname} = $1;

So, you have the tool to write such a program for you, by doing
something like this:

	my $template = '
                $refname = %(refname);
                $authorline = %(author);
                $authorline =~ /^author\s.*\s(\d+)\s[-+]\d{4}$/;
                $branch_date{$refname} = $1;
	';
        my @cmd = ('git-for-each-ref', '--perl', "--format=$template");

	open I, '-|', @cmd, 'refs/heads';
        my $script = join('',<I>);
        close I;

	my ($refname, $authorline);
        eval "$script";

The language specific quoting flag --perl affects how %() are
interpolated into the generated program text as literals.
That's why there is no quote around %(refname) or %(author)
in the example above when defining the $template.

Re: [PATCH] cvsimport move over to using git for each ref to read refs

From: Andy Whitcroft <hidden>
Date: 2016-06-15 22:42:41

Junio C Hamano wrote:
Andy Whitcroft [off-list ref] writes:
quoted
I guess we could teach for-each-ref to output this as well?  Perhaps
something like authorstamp?
I think you can work with "author" or "committer" to grab the
whole raw line.

About the quoting and parsing, language specific quoting mode is
meant for git-for-each-ref to produce a string that can be eval'ed
in the host language.  Think of the command as a tool to write a
short program for you.
Thanks for the education.  Very simple, and very powerful.  I knew there
was a reason for it out there.  Will respin a V3 patch in a bit.

-apw

[PATCH] cvsimport move over to using git for each ref to read refs V3

From: Andy Whitcroft <hidden>
Date: 2016-06-15 22:42:41

cvsimport: move over to using git-for-each-ref to read refs V3

cvsimport opens all of the files in $GIT_DIR/refs/heads and reads
out the sha1's in order to work out what time the last commit on
that branch was made (in CVS) thus allowing incremental updates.
However, this takes no account of hierachical refs naming producing
the following error for each directory in $GIT_DIR/refs:

  Use of uninitialized value in chomp at /usr/bin/git-cvsimport line 503.
  Use of uninitialized value in concatenation (.) or string at
					/usr/bin/git-cvsimport line 505.
  usage: git-cat-file [-t|-s|-e|-p|<type>] <sha1>

Take advantage of the new packed refs work to use the new
for-each-ref iterator to get this information.

Signed-off-by: Andy Whitcroft <redacted>
---
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index e5a00a1..92d14c3 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -495,22 +495,19 @@ unless(-d $git_dir) {
 	$tip_at_start = `git-rev-parse --verify HEAD`;
 
 	# Get the last import timestamps
-	opendir(D,"$git_dir/refs/heads");
-	while(defined(my $head = readdir(D))) {
-		next if $head =~ /^\./;
-		open(F,"$git_dir/refs/heads/$head")
-			or die "Bad head branch: $head: $!\n";
-		chomp(my $ftag = <F>);
-		close(F);
-		open(F,"git-cat-file commit $ftag |");
-		while(<F>) {
-			next unless /^author\s.*\s(\d+)\s[-+]\d{4}$/;
-			$branch_date{$head} = $1;
-			last;
-		}
-		close(F);
+	my $fmt = '($ref, $author) = (%(refname), %(author));';
+	open(H, "git-for-each-ref --perl --format='$fmt'|") or
+		die "Cannot run git-for-each-ref: $!\n";
+	while(defined(my $entry = <H>)) {
+		my ($ref, $author);
+		eval($entry) || die "cannot eval refs list: $@";
+
+		next if ($ref !~ m@^refs/heads/(.*)$@);
+		my ($head) = ($1);
+		$author =~ /^.*\s(\d+)\s[-+]\d{4}$/;
+		$branch_date{$head} = $1;
 	}
-	closedir(D);
+	close(H);
 }
 
 -d $git_dir
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help