git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jacob Kroon <jacob.kroon@gmail.com>
To: Jon Nelson <jnelson-git@jamponi.net>
Cc: git@vger.kernel.org
Subject: Re: Fixing author/email fields in commit messages
Date: Mon, 20 Feb 2006 02:21:25 +0100	[thread overview]
Message-ID: <43F91995.10304@gmail.com> (raw)
In-Reply-To: <Pine.LNX.4.63.0602191729100.6352@gheavc.wnzcbav.cig>

[-- Attachment #1: Type: text/plain, Size: 783 bytes --]

After some more private discussion (I forgot to CC the mailing list) 
with Jon Nelson,
he came up with this strategy for fixing the author/email part of commit 
messages:

0. Make a backup copy of the repository, just in case.

1. Setup your GIT_AUTHOR_xxx/GIT_COMMITTER_xxx env. variables correctly.

2. Apply the attached patch to recent git sources. (patch made by Jon 
Nelson).

3. Run the patched git-convert-objects, passing HEAD as argument.

4. Run "git-update-ref HEAD 'newsha1'", where 'newsha1' is the output 
from the previous command.

5. Run "git-prune" to get rid of the old stale object files.

This worked for me, but I guess there are no warranties 8)
In case you have multiple branches you might need to repeat the 
procedure for each branch.

thanks Jon

//Jacob

[-- Attachment #2: convert-objects.diff --]
[-- Type: text/x-patch, Size: 9372 bytes --]

diff --git a/convert-objects.c b/convert-objects.c
index b49bce2..109bfb0 100644
--- a/convert-objects.c
+++ b/convert-objects.c
@@ -263,7 +263,156 @@ static void convert_date(void *buffer, u
 	newlen += size;
 
 	write_sha1_file(new, newlen, "commit", result_sha1);
-	free(new);	
+	free(new);
+}
+
+static int convert_email_line(char *dst, void **buf, unsigned long *sp, const char *name, const char *new_email)
+{
+        unsigned long size = *sp;
+        char *line = *buf;
+        char *space = strchr(line, ' ');
+	char *next = strchr(line, '\n');
+	char *email_start = strchr(line, '<');
+        char *email_end = strchr(line, '>');
+        int len, total = 0;
+
+	// "author|committer xyz <xyz> date"
+        // "committer xyz <xyz> date"
+	if (!space || !next || !email_start || !email_end)
+            die("missing or bad author/committer line %s", line);
+
+        ++space;
+        ++email_start;
+        ++next;
+
+        //fprintf(stderr, "yikes: size; %lu \"%s\"\n", size, line);
+
+        *buf = next;
+        *sp = size - (next - line);
+
+        /* copy the stuff from before the name */
+        len = space - line;
+        memcpy(dst, line, len);
+        dst += len;
+        total += len;
+        size -= len;
+
+        /* copy the new name */
+        len = strlen(name);
+        memcpy(dst, name, len);
+        dst += len;
+        total += len;
+        size -= len;
+
+        /* put a space in there */
+        *dst = ' ';
+        ++dst;
+        ++total;
+        --size;
+
+        /* put a '<' in there */
+        *dst = '<';
+        ++dst;
+        ++total;
+        --size;
+
+        /* copy the new email */
+        len = strlen(new_email);
+        memcpy(dst, new_email, len);
+        dst += len;
+        total += len;
+        size -= len;
+
+        /* copy the rest of the line */
+        len = next - email_end;
+        memcpy(dst, email_end, len);
+        dst += len;
+        total += len;
+        size -= len;
+
+        return total;
+}
+
+static void convert_authorcommitter(void *buffer, unsigned long size, unsigned char *result_sha1)
+{
+	char *new = xmalloc(size + 100);
+        unsigned long newlen = 0;
+        char *author_info = strdup(git_author_info());
+        char *committer_info = strdup(git_committer_info());
+        char *author_name, *author_email;
+        char *committer_name, *committer_email;
+        char *temp;
+
+//#define TESTING
+#ifdef TESTING
+        fprintf(stderr, "author_info: \"%s\"\n",
+                author_info);
+        fprintf(stderr, "committer_info: \"%s\"\n",
+                committer_info);
+#endif
+        author_name = author_info;
+        temp = strchr(author_name, '<');
+        if (!temp)
+            die("Unable to find valid name address.");
+        --temp;
+        *temp = '\0';
+        temp += 2;
+
+        author_email = temp;
+        temp = strrchr(author_email, '>');
+        if (!temp)
+            die("Unable to find valid email address.");
+        *temp = '\0';
+
+        committer_name = committer_info;
+        temp = strchr(committer_name, '<');
+        if (!temp)
+            die("Unable to find valid name address.");
+        --temp;
+        *temp = '\0';
+        temp += 2;
+
+        committer_email = temp;
+        temp = strrchr(committer_email, '>');
+        if (!temp)
+            die("Unable to find valid email address.");
+        *temp = '\0';
+
+#ifdef TESTING
+        fprintf(stderr, "author_name: \"%s\"\n", author_name);
+        fprintf(stderr, "author_email: \"%s\"\n", author_email);
+        fprintf(stderr, "committer_name: \"%s\"\n", committer_name);
+        fprintf(stderr, "committer_email: \"%s\"\n", committer_email);
+        exit(0);
+#endif
+
+	// "tree <sha1>\n"
+	memcpy(new + newlen, buffer, 46);
+	newlen += 46;
+	buffer += 46;
+	size -= 46;
+
+	// "parent <sha1>\n"
+	while (!memcmp(buffer, "parent ", 7)) {
+		memcpy(new + newlen, buffer, 48);
+		newlen += 48;
+		buffer += 48;
+		size -= 48;
+	}
+
+	// "author xyz <xyz> date"
+	// "committer xyz <xyz> date"
+        newlen += convert_email_line(new + newlen, &buffer, &size, author_name, author_email);
+        newlen += convert_email_line(new + newlen, &buffer, &size, committer_name, committer_email);
+
+	// Rest
+	memcpy(new + newlen, buffer, size);
+	newlen += size;
+
+	write_sha1_file(new, newlen, "commit", result_sha1);
+        free(new);
+        free(author_info);
+        free(committer_info);
 }
 
 static void convert_commit(void *buffer, unsigned long size, unsigned char *result_sha1)
@@ -279,7 +428,117 @@ static void convert_commit(void *buffer,
 		convert_ascii_sha1(buffer+7);
 		buffer += 48;
 	}
-	convert_date(orig_buffer, orig_size, result_sha1);
+	convert_authorcommitter(orig_buffer, orig_size, result_sha1);
+}
+
+static void convert_tag(void *buffer, unsigned long size, unsigned char *result_sha1)
+{
+	void *orig_buffer = buffer;
+
+	char *new = xmalloc(size + 100);
+        unsigned long newlen = 0;
+
+        char *author_info = strdup(git_author_info());
+        char *committer_info = strdup(git_committer_info());
+        char *author_name, *author_email;
+        char *committer_name, *committer_email;
+        char *temp;
+        unsigned long len = 0;
+        char *email_start;
+        char *email_end;
+        char *author_start;
+        int has_author = 1;
+
+        author_name = author_info;
+        temp = strchr(author_name, '<');
+        if (!temp)
+            die("Unable to find valid name address.");
+        --temp;
+        *temp = '\0';
+        temp += 2;
+
+        author_email = temp;
+        temp = strrchr(author_email, '>');
+        if (!temp)
+            die("Unable to find valid email address.");
+        *temp = '\0';
+
+        committer_name = committer_info;
+        temp = strchr(committer_name, '<');
+        if (!temp)
+            die("Unable to find valid name address.");
+        --temp;
+        *temp = '\0';
+        temp += 2;
+
+        committer_email = temp;
+        temp = strrchr(committer_email, '>');
+        if (!temp)
+            die("Unable to find valid email address.");
+        *temp = '\0';
+
+        //* START *//
+
+	if (memcmp(buffer, "object ", 7))
+		die("Bad tag '%s'", (char*) buffer);
+        convert_ascii_sha1(buffer+7);
+//        fprintf(stderr, "converting %s", (char *) (buffer + 7));
+        buffer += 7 + 40 + 1;    /* "object " + "hex sha1" + "\n" */
+        /* type commit
+           tag boa-0.94.14rc6
+           tagger...
+           */
+        /* with tagger, we check for tagger author_name <author_email>
+         * and if so, we convert that, too
+         */
+        temp = strchr(buffer, '\n'); /* end of commit line */
+        if (!temp) {
+            die("Bad tag '%s'", (char *) buffer);
+        }
+        ++temp;
+        temp = strchr(temp, '\n'); /* end of tag line */
+        if (!temp) {
+            die("Bad tag '%s'", (char *) buffer);
+        }
+        ++temp;
+        if (memcmp(temp, "tagger ", 7))
+            die("Bad tag '%s'", (char *) buffer);
+        temp += 7; /* just after 'tagger ' */
+
+        len = (temp - (char *) orig_buffer);
+        memcpy(new, orig_buffer, len);
+        newlen += len;
+        ++temp;
+
+        /* check to see if the next item looks like an name + email */
+        email_start = strchr(temp, '<');
+        if (email_start) {
+            email_end = strchr(email_start, '>');
+            if (email_end) {
+                author_start = strchr(temp, ' ');
+                if (author_start && author_start < email_start) {
+                    has_author = 1;
+                    newlen += sprintf(new + newlen,
+                                      "%s <%s>\n",
+                                      author_name,
+                                      author_email);
+                    len = (email_end - (char *) buffer) + 2;
+                }
+
+            }
+        }
+
+        if (len > size) {
+            memcpy(new + newlen, orig_buffer + len, size - len);
+            newlen += (size - len);
+        }
+//        fprintf(stderr, "About to write: %s", new);
+//        exit(0);
+
+        write_sha1_file(new, newlen, "tag", result_sha1);
+        free(new);
+        free(author_info);
+        free(committer_info);
 }
 
 static struct entry * convert_entry(unsigned char *sha1)
@@ -297,13 +556,15 @@ static struct entry * convert_entry(unsi
 
 	buffer = xmalloc(size);
 	memcpy(buffer, data, size);
-	
+
 	if (!strcmp(type, "blob")) {
 		write_sha1_file(buffer, size, "blob", entry->new_sha1);
-	} else if (!strcmp(type, "tree"))
-		convert_tree(buffer, size, entry->new_sha1);
-	else if (!strcmp(type, "commit"))
-		convert_commit(buffer, size, entry->new_sha1);
+        } else if (!strcmp(type, "tree"))
+            convert_tree(buffer, size, entry->new_sha1);
+        else if (!strcmp(type, "commit"))
+            convert_commit(buffer, size, entry->new_sha1);
+        else if (!strcmp(type, "tag"))
+            convert_tag(buffer, size, entry->new_sha1);
 	else
 		die("unknown object type '%s' in %s", type, sha1_to_hex(sha1));
 	entry->converted = 1;
@@ -318,6 +579,7 @@ int main(int argc, char **argv)
 	struct entry *entry;
 
 	setup_git_directory();
+	setup_ident();
 
 	if (argc != 2 || get_sha1(argv[1], sha1))
 		usage("git-convert-objects <sha1>");

      reply	other threads:[~2006-02-20  1:15 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-02-19 18:45 Fixing author/email fields in commit messages Jacob Kroon
2006-02-19 19:27 ` Johannes Schindelin
2006-02-19 21:24 ` Sam Vilain
2006-02-19 22:35 ` Jon Nelson
2006-02-19 23:01   ` Jon Nelson
2006-02-19 23:33     ` Jacob Kroon
2006-02-19 23:34       ` Jon Nelson
2006-02-20  1:21         ` Jacob Kroon [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=43F91995.10304@gmail.com \
    --to=jacob.kroon@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=jnelson-git@jamponi.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).