{"thread":{"id":"3395","subject":"Fixing author/email fields in commit messages","startedAt":"2006-02-19T18:45:05Z","lastAt":"2006-02-20T01:21:25Z","messageCount":8,"participants":["Jacob Kroon","Johannes Schindelin","Sam Vilain","Jon Nelson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"16414","messageId":"43F8BCB1.2010701@gmail.com","threadId":"3395","inReplyTo":null,"subject":"Fixing author/email fields in commit messages","fromName":"Jacob Kroon","fromEmail":"jacob.kroon@gmail.com","sentAt":"2006-02-19T18:45:05Z","receivedAt":"2006-02-19T18:45:05Z","isPatch":false,"sender":{"key":"jacob.kroon@gmail.com","avatar":null},"body":"When I started my git repository for my project, I never setup \nGIT_AUTHOR_NAME etc. correctly,\nso my commit messages used the default information, \n\"<jacob@skeletor.(none)>\", \"skeletor\" being the\nhostname of the computer I'm working on. I'd like to change it so that \nthe messages will contain correct\ninformation about my e-mail and username. I noticed that this question \nhas been brought up here before\nand that the solution might be to use git-convert-objects, but that it \nmight need some modifications.\n\nHas anyone come up with a working tool for this task ?\n\nI know how to make the future commits look as expected.\n\n//Jacob\n"},{"id":"16417","messageId":"Pine.LNX.4.63.0602192025170.11855@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"3395","inReplyTo":"43F8BCB1.2010701@gmail.com","subject":"Re: Fixing author/email fields in commit messages","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-02-19T19:27:15Z","receivedAt":"2006-02-19T19:27:15Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 19 Feb 2006, Jacob Kroon wrote:\n\n> When I started my git repository for my project, I never setup \n> GIT_AUTHOR_NAME etc. correctly, so my commit messages used the default \n> information, \"<jacob@skeletor.(none)>\", \"skeletor\" being the hostname of \n> the computer I'm working on. I'd like to change it so that the messages \n> will contain correct information about my e-mail and username. I noticed \n> that this question has been brought up here before and that the solution \n> might be to use git-convert-objects, but that it might need some \n> modifications.\n> \n> Has anyone come up with a working tool for this task ?\n\nUnfortunately not.\n\nHowever, I'd rather start by enhancing git-rebase. You do not really need \nto rewrite *all* objects, but only the *commit objects*. Two things seem \nto be lacking for what you want:\n\n\t- an option to rebase \"onto an empty commit\", and\n\t- an optional filter command to run on the commit messages.\n\nHth,\nDscho\n"},{"id":"16424","messageId":"43F8E207.9020306@vilain.net","threadId":"3395","inReplyTo":"43F8BCB1.2010701@gmail.com","subject":"Re: Fixing author/email fields in commit messages","fromName":"Sam Vilain","fromEmail":"sam@vilain.net","sentAt":"2006-02-19T21:24:23Z","receivedAt":"2006-02-19T21:24:23Z","isPatch":false,"sender":{"key":"sam@vilain.net","avatar":"https://gravatar.com/avatar/8fc840ca854dbf6f7065b4335e3b934951c1dca3b11db688e95e471901f8f4a8?d=mp&s=160"},"body":"Jacob Kroon wrote:\n> When I started my git repository for my project, I never setup \n> GIT_AUTHOR_NAME etc. correctly,\n> so my commit messages used the default information, \n> \"<jacob@skeletor.(none)>\", \"skeletor\" being the\n> hostname of the computer I'm working on. I'd like to change it so that \n> the messages will contain correct\n> information about my e-mail and username. I noticed that this question \n> has been brought up here before\n> and that the solution might be to use git-convert-objects, but that it \n> might need some modifications.\n> \n> Has anyone come up with a working tool for this task ?\n\nPerhaps \"stg uncommit\"\n\nSam.\n"},{"id":"16426","messageId":"Pine.LNX.4.63.0602191634480.6352@gheavc.wnzcbav.cig","threadId":"3395","inReplyTo":"43F8BCB1.2010701@gmail.com","subject":"Re: Fixing author/email fields in commit messages","fromName":"Jon Nelson","fromEmail":"jnelson-git@jamponi.net","sentAt":"2006-02-19T22:35:47Z","receivedAt":"2006-02-19T22:35:47Z","isPatch":false,"sender":{"key":"jnelson-git@jamponi.net","avatar":null},"body":"On Sun, 19 Feb 2006, Jacob Kroon wrote:\n\n> When I started my git repository for my project, I never setup GIT_AUTHOR_NAME\n> etc. correctly,\n> so my commit messages used the default information, \"<jacob@skeletor.(none)>\",\n> \"skeletor\" being the\n> hostname of the computer I'm working on. I'd like to change it so that the\n> messages will contain correct\n> information about my e-mail and username. I noticed that this question has\n> been brought up here before\n> and that the solution might be to use git-convert-objects, but that it might\n> need some modifications.\n> \n> Has anyone come up with a working tool for this task ?\n\nI modified git-convert-objects to perform just that task.\nI'll see if I can dig it up (I'm not able to do so right now).\n\n--\nJon Nelson <jnelson-git@jamponi.net>\n"},{"id":"16427","messageId":"Pine.LNX.4.63.0602191651340.6352@gheavc.wnzcbav.cig","threadId":"3395","inReplyTo":"Pine.LNX.4.63.0602191634480.6352@gheavc.wnzcbav.cig","subject":"Re: Fixing author/email fields in commit messages","fromName":"Jon Nelson","fromEmail":"jnelson-git@jamponi.net","sentAt":"2006-02-19T23:01:03Z","receivedAt":"2006-02-19T23:01:03Z","isPatch":false,"sender":{"key":"jnelson-git@jamponi.net","avatar":null},"body":"\nOn Sun, 19 Feb 2006, Jon Nelson wrote:\n\n> On Sun, 19 Feb 2006, Jacob Kroon wrote:\n> \n> > When I started my git repository for my project, I never setup GIT_AUTHOR_NAME\n> > etc. correctly,\n> > so my commit messages used the default information, \"<jacob@skeletor.(none)>\",\n> > \"skeletor\" being the\n> > hostname of the computer I'm working on. I'd like to change it so that the\n> > messages will contain correct\n> > information about my e-mail and username. I noticed that this question has\n> > been brought up here before\n> > and that the solution might be to use git-convert-objects, but that it might\n> > need some modifications.\n> > \n> > Has anyone come up with a working tool for this task ?\n> \n> I modified git-convert-objects to perform just that task.\n> I'll see if I can dig it up (I'm not able to do so right now).\n\nAttached. Notes:\n\n1. it's ugly\n2. it's indented funny\n3. it didn't seem to break anything for me, but no guarantees\n4. it probably smells of elderberries\n5. set your GIT_* environment up properly first or you'll wonder why it \ndoesn't work like I did.\n\n--\nJon Nelson <jnelson-git@jamponi.net>\n\ndiff --git a/convert-objects.c b/convert-objects.c\nindex b49bce2..109bfb0 100644\n--- a/convert-objects.c\n+++ b/convert-objects.c\n@@ -263,7 +263,156 @@ static void convert_date(void *buffer, u\n \tnewlen += size;\n \n \twrite_sha1_file(new, newlen, \"commit\", result_sha1);\n-\tfree(new);\t\n+\tfree(new);\n+}\n+\n+static int convert_email_line(char *dst, void **buf, unsigned long *sp, const char *name, const char *new_email)\n+{\n+        unsigned long size = *sp;\n+        char *line = *buf;\n+        char *space = strchr(line, ' ');\n+\tchar *next = strchr(line, '\\n');\n+\tchar *email_start = strchr(line, '<');\n+        char *email_end = strchr(line, '>');\n+        int len, total = 0;\n+\n+\t// \"author|committer xyz <xyz> date\"\n+        // \"committer xyz <xyz> date\"\n+\tif (!space || !next || !email_start || !email_end)\n+            die(\"missing or bad author/committer line %s\", line);\n+\n+        ++space;\n+        ++email_start;\n+        ++next;\n+\n+        //fprintf(stderr, \"yikes: size; %lu \\\"%s\\\"\\n\", size, line);\n+\n+        *buf = next;\n+        *sp = size - (next - line);\n+\n+        /* copy the stuff from before the name */\n+        len = space - line;\n+        memcpy(dst, line, len);\n+        dst += len;\n+        total += len;\n+        size -= len;\n+\n+        /* copy the new name */\n+        len = strlen(name);\n+        memcpy(dst, name, len);\n+        dst += len;\n+        total += len;\n+        size -= len;\n+\n+        /* put a space in there */\n+        *dst = ' ';\n+        ++dst;\n+        ++total;\n+        --size;\n+\n+        /* put a '<' in there */\n+        *dst = '<';\n+        ++dst;\n+        ++total;\n+        --size;\n+\n+        /* copy the new email */\n+        len = strlen(new_email);\n+        memcpy(dst, new_email, len);\n+        dst += len;\n+        total += len;\n+        size -= len;\n+\n+        /* copy the rest of the line */\n+        len = next - email_end;\n+        memcpy(dst, email_end, len);\n+        dst += len;\n+        total += len;\n+        size -= len;\n+\n+        return total;\n+}\n+\n+static void convert_authorcommitter(void *buffer, unsigned long size, unsigned char *result_sha1)\n+{\n+\tchar *new = xmalloc(size + 100);\n+        unsigned long newlen = 0;\n+        char *author_info = strdup(git_author_info());\n+        char *committer_info = strdup(git_committer_info());\n+        char *author_name, *author_email;\n+        char *committer_name, *committer_email;\n+        char *temp;\n+\n+//#define TESTING\n+#ifdef TESTING\n+        fprintf(stderr, \"author_info: \\\"%s\\\"\\n\",\n+                author_info);\n+        fprintf(stderr, \"committer_info: \\\"%s\\\"\\n\",\n+                committer_info);\n+#endif\n+        author_name = author_info;\n+        temp = strchr(author_name, '<');\n+        if (!temp)\n+            die(\"Unable to find valid name address.\");\n+        --temp;\n+        *temp = '\\0';\n+        temp += 2;\n+\n+        author_email = temp;\n+        temp = strrchr(author_email, '>');\n+        if (!temp)\n+            die(\"Unable to find valid email address.\");\n+        *temp = '\\0';\n+\n+        committer_name = committer_info;\n+        temp = strchr(committer_name, '<');\n+        if (!temp)\n+            die(\"Unable to find valid name address.\");\n+        --temp;\n+        *temp = '\\0';\n+        temp += 2;\n+\n+        committer_email = temp;\n+        temp = strrchr(committer_email, '>');\n+        if (!temp)\n+            die(\"Unable to find valid email address.\");\n+        *temp = '\\0';\n+\n+#ifdef TESTING\n+        fprintf(stderr, \"author_name: \\\"%s\\\"\\n\", author_name);\n+        fprintf(stderr, \"author_email: \\\"%s\\\"\\n\", author_email);\n+        fprintf(stderr, \"committer_name: \\\"%s\\\"\\n\", committer_name);\n+        fprintf(stderr, \"committer_email: \\\"%s\\\"\\n\", committer_email);\n+        exit(0);\n+#endif\n+\n+\t// \"tree <sha1>\\n\"\n+\tmemcpy(new + newlen, buffer, 46);\n+\tnewlen += 46;\n+\tbuffer += 46;\n+\tsize -= 46;\n+\n+\t// \"parent <sha1>\\n\"\n+\twhile (!memcmp(buffer, \"parent \", 7)) {\n+\t\tmemcpy(new + newlen, buffer, 48);\n+\t\tnewlen += 48;\n+\t\tbuffer += 48;\n+\t\tsize -= 48;\n+\t}\n+\n+\t// \"author xyz <xyz> date\"\n+\t// \"committer xyz <xyz> date\"\n+        newlen += convert_email_line(new + newlen, &buffer, &size, author_name, author_email);\n+        newlen += convert_email_line(new + newlen, &buffer, &size, committer_name, committer_email);\n+\n+\t// Rest\n+\tmemcpy(new + newlen, buffer, size);\n+\tnewlen += size;\n+\n+\twrite_sha1_file(new, newlen, \"commit\", result_sha1);\n+        free(new);\n+        free(author_info);\n+        free(committer_info);\n }\n \n static void convert_commit(void *buffer, unsigned long size, unsigned char *result_sha1)\n@@ -279,7 +428,117 @@ static void convert_commit(void *buffer,\n \t\tconvert_ascii_sha1(buffer+7);\n \t\tbuffer += 48;\n \t}\n-\tconvert_date(orig_buffer, orig_size, result_sha1);\n+\tconvert_authorcommitter(orig_buffer, orig_size, result_sha1);\n+}\n+\n+static void convert_tag(void *buffer, unsigned long size, unsigned char *result_sha1)\n+{\n+\tvoid *orig_buffer = buffer;\n+\n+\tchar *new = xmalloc(size + 100);\n+        unsigned long newlen = 0;\n+\n+        char *author_info = strdup(git_author_info());\n+        char *committer_info = strdup(git_committer_info());\n+        char *author_name, *author_email;\n+        char *committer_name, *committer_email;\n+        char *temp;\n+        unsigned long len = 0;\n+        char *email_start;\n+        char *email_end;\n+        char *author_start;\n+        int has_author = 1;\n+\n+        author_name = author_info;\n+        temp = strchr(author_name, '<');\n+        if (!temp)\n+            die(\"Unable to find valid name address.\");\n+        --temp;\n+        *temp = '\\0';\n+        temp += 2;\n+\n+        author_email = temp;\n+        temp = strrchr(author_email, '>');\n+        if (!temp)\n+            die(\"Unable to find valid email address.\");\n+        *temp = '\\0';\n+\n+        committer_name = committer_info;\n+        temp = strchr(committer_name, '<');\n+        if (!temp)\n+            die(\"Unable to find valid name address.\");\n+        --temp;\n+        *temp = '\\0';\n+        temp += 2;\n+\n+        committer_email = temp;\n+        temp = strrchr(committer_email, '>');\n+        if (!temp)\n+            die(\"Unable to find valid email address.\");\n+        *temp = '\\0';\n+\n+        //* START *//\n+\n+\tif (memcmp(buffer, \"object \", 7))\n+\t\tdie(\"Bad tag '%s'\", (char*) buffer);\n+        convert_ascii_sha1(buffer+7);\n+//        fprintf(stderr, \"converting %s\", (char *) (buffer + 7));\n+        buffer += 7 + 40 + 1;    /* \"object \" + \"hex sha1\" + \"\\n\" */\n+        /* type commit\n+           tag boa-0.94.14rc6\n+           tagger...\n+           */\n+        /* with tagger, we check for tagger author_name <author_email>\n+         * and if so, we convert that, too\n+         */\n+        temp = strchr(buffer, '\\n'); /* end of commit line */\n+        if (!temp) {\n+            die(\"Bad tag '%s'\", (char *) buffer);\n+        }\n+        ++temp;\n+        temp = strchr(temp, '\\n'); /* end of tag line */\n+        if (!temp) {\n+            die(\"Bad tag '%s'\", (char *) buffer);\n+        }\n+        ++temp;\n+        if (memcmp(temp, \"tagger \", 7))\n+            die(\"Bad tag '%s'\", (char *) buffer);\n+        temp += 7; /* just after 'tagger ' */\n+\n+        len = (temp - (char *) orig_buffer);\n+        memcpy(new, orig_buffer, len);\n+        newlen += len;\n+        ++temp;\n+\n+        /* check to see if the next item looks like an name + email */\n+        email_start = strchr(temp, '<');\n+        if (email_start) {\n+            email_end = strchr(email_start, '>');\n+            if (email_end) {\n+                author_start = strchr(temp, ' ');\n+                if (author_start && author_start < email_start) {\n+                    has_author = 1;\n+                    newlen += sprintf(new + newlen,\n+                                      \"%s <%s>\\n\",\n+                                      author_name,\n+                                      author_email);\n+                    len = (email_end - (char *) buffer) + 2;\n+                }\n+\n+            }\n+        }\n+\n+        if (len > size) {\n+            memcpy(new + newlen, orig_buffer + len, size - len);\n+            newlen += (size - len);\n+        }\n+//        fprintf(stderr, \"About to write: %s\", new);\n+//        exit(0);\n+\n+        write_sha1_file(new, newlen, \"tag\", result_sha1);\n+        free(new);\n+        free(author_info);\n+        free(committer_info);\n }\n \n static struct entry * convert_entry(unsigned char *sha1)\n@@ -297,13 +556,15 @@ static struct entry * convert_entry(unsi\n \n \tbuffer = xmalloc(size);\n \tmemcpy(buffer, data, size);\n-\t\n+\n \tif (!strcmp(type, \"blob\")) {\n \t\twrite_sha1_file(buffer, size, \"blob\", entry->new_sha1);\n-\t} else if (!strcmp(type, \"tree\"))\n-\t\tconvert_tree(buffer, size, entry->new_sha1);\n-\telse if (!strcmp(type, \"commit\"))\n-\t\tconvert_commit(buffer, size, entry->new_sha1);\n+        } else if (!strcmp(type, \"tree\"))\n+            convert_tree(buffer, size, entry->new_sha1);\n+        else if (!strcmp(type, \"commit\"))\n+            convert_commit(buffer, size, entry->new_sha1);\n+        else if (!strcmp(type, \"tag\"))\n+            convert_tag(buffer, size, entry->new_sha1);\n \telse\n \t\tdie(\"unknown object type '%s' in %s\", type, sha1_to_hex(sha1));\n \tentry->converted = 1;\n@@ -318,6 +579,7 @@ int main(int argc, char **argv)\n \tstruct entry *entry;\n \n \tsetup_git_directory();\n+\tsetup_ident();\n \n \tif (argc != 2 || get_sha1(argv[1], sha1))\n \t\tusage(\"git-convert-objects <sha1>\");\n"},{"id":"16428","messageId":"43F9005E.30901@gmail.com","threadId":"3395","inReplyTo":"Pine.LNX.4.63.0602191651340.6352@gheavc.wnzcbav.cig","subject":"Re: Fixing author/email fields in commit messages","fromName":"Jacob Kroon","fromEmail":"jacob.kroon@gmail.com","sentAt":"2006-02-19T23:33:50Z","receivedAt":"2006-02-19T23:33:50Z","isPatch":false,"sender":{"key":"jacob.kroon@gmail.com","avatar":null},"body":"Jon Nelson wrote:\n\n>>I modified git-convert-objects to perform just that task.\n>>I'll see if I can dig it up (I'm not able to do so right now).\n>>    \n>>\n>\n>Attached. Notes:\n>\n>1. it's ugly\n>2. it's indented funny\n>3. it didn't seem to break anything for me, but no guarantees\n>4. it probably smells of elderberries\n>5. set your GIT_* environment up properly first or you'll wonder why it \n>doesn't work like I did.\n>\n>  \n>\nHi Jon,\n\nI've applied your patch to the latest git sources, and it compiles, but \nI'm not quite sure how to\ninvoke the command. I've setup GIT_* env. variables, and \ngit-convert-objects needs a sha1 identifier.\nI've tried passing \"HEAD\", and some other commit id's, but they don't \nseem to make any difference.\nAm I doing things right ? How exactly do I invoke the command to clean \nup the commit messages ?\n\nAt least I don't get any error messages.\n\n//Jacob\n"},{"id":"16433","messageId":"Pine.LNX.4.63.0602191729100.6352@gheavc.wnzcbav.cig","threadId":"3395","inReplyTo":"43F9005E.30901@gmail.com","subject":"Re: Fixing author/email fields in commit messages","fromName":"Jon Nelson","fromEmail":"jnelson-git@jamponi.net","sentAt":"2006-02-19T23:34:17Z","receivedAt":"2006-02-19T23:34:17Z","isPatch":false,"sender":{"key":"jnelson-git@jamponi.net","avatar":null},"body":"On Mon, 20 Feb 2006, Jacob Kroon wrote:\n\n> Jon Nelson wrote:\n> \n> > >I modified git-convert-objects to perform just that task.\n> > >I'll see if I can dig it up (I'm not able to do so right now).\n> > >    \n> > >\n> >\n> >Attached. Notes:\n> >\n> >1. it's ugly\n> >2. it's indented funny\n> >3. it didn't seem to break anything for me, but no guarantees\n> >4. it probably smells of elderberries\n> >5. set your GIT_* environment up properly first or you'll wonder why it\n> >doesn't work like I did.\n> >\n> >  \n> >\n> Hi Jon,\n> \n> I've applied your patch to the latest git sources, and it compiles, but I'm\n> not quite sure how to\n> invoke the command. I've setup GIT_* env. variables, and git-convert-objects\n> needs a sha1 identifier.\n> I've tried passing \"HEAD\", and some other commit id's, but they don't seem to\n> make any difference.\n> Am I doing things right ? How exactly do I invoke the command to clean up the\n> commit messages ?\n> \n> At least I don't get any error messages.\n\nIf I recall properly, it should be sufficient to invoke it with the sha1 \nof the HEAD branch.  \n\nThus, you could use:\n\ngit-convert-objects $(git-rev-list --max-count=1 HEAD)\n\nTo do /all/ of the branches:\n\nfor branch in $(cat .git/refs/heads/* | sort | uniq); do\n  git-convert-objects ${branch}\ndone\n\nIt should work on tags, too, although I only tested on my own git stuff \nwhich was converted from cvs.\n\n--\nJon Nelson <jnelson-git@jamponi.net>\n"},{"id":"16434","messageId":"43F91995.10304@gmail.com","threadId":"3395","inReplyTo":"Pine.LNX.4.63.0602191729100.6352@gheavc.wnzcbav.cig","subject":"Re: Fixing author/email fields in commit messages","fromName":"Jacob Kroon","fromEmail":"jacob.kroon@gmail.com","sentAt":"2006-02-20T01:21:25Z","receivedAt":"2006-02-20T01:21:25Z","isPatch":false,"sender":{"key":"jacob.kroon@gmail.com","avatar":null},"body":"After some more private discussion (I forgot to CC the mailing list) \nwith Jon Nelson,\nhe came up with this strategy for fixing the author/email part of commit \nmessages:\n\n0. Make a backup copy of the repository, just in case.\n\n1. Setup your GIT_AUTHOR_xxx/GIT_COMMITTER_xxx env. variables correctly.\n\n2. Apply the attached patch to recent git sources. (patch made by Jon \nNelson).\n\n3. Run the patched git-convert-objects, passing HEAD as argument.\n\n4. Run \"git-update-ref HEAD 'newsha1'\", where 'newsha1' is the output \nfrom the previous command.\n\n5. Run \"git-prune\" to get rid of the old stale object files.\n\nThis worked for me, but I guess there are no warranties 8)\nIn case you have multiple branches you might need to repeat the \nprocedure for each branch.\n\nthanks Jon\n\n//Jacob\n\n\ndiff --git a/convert-objects.c b/convert-objects.c\nindex b49bce2..109bfb0 100644\n--- a/convert-objects.c\n+++ b/convert-objects.c\n@@ -263,7 +263,156 @@ static void convert_date(void *buffer, u\n \tnewlen += size;\n \n \twrite_sha1_file(new, newlen, \"commit\", result_sha1);\n-\tfree(new);\t\n+\tfree(new);\n+}\n+\n+static int convert_email_line(char *dst, void **buf, unsigned long *sp, const char *name, const char *new_email)\n+{\n+        unsigned long size = *sp;\n+        char *line = *buf;\n+        char *space = strchr(line, ' ');\n+\tchar *next = strchr(line, '\\n');\n+\tchar *email_start = strchr(line, '<');\n+        char *email_end = strchr(line, '>');\n+        int len, total = 0;\n+\n+\t// \"author|committer xyz <xyz> date\"\n+        // \"committer xyz <xyz> date\"\n+\tif (!space || !next || !email_start || !email_end)\n+            die(\"missing or bad author/committer line %s\", line);\n+\n+        ++space;\n+        ++email_start;\n+        ++next;\n+\n+        //fprintf(stderr, \"yikes: size; %lu \\\"%s\\\"\\n\", size, line);\n+\n+        *buf = next;\n+        *sp = size - (next - line);\n+\n+        /* copy the stuff from before the name */\n+        len = space - line;\n+        memcpy(dst, line, len);\n+        dst += len;\n+        total += len;\n+        size -= len;\n+\n+        /* copy the new name */\n+        len = strlen(name);\n+        memcpy(dst, name, len);\n+        dst += len;\n+        total += len;\n+        size -= len;\n+\n+        /* put a space in there */\n+        *dst = ' ';\n+        ++dst;\n+        ++total;\n+        --size;\n+\n+        /* put a '<' in there */\n+        *dst = '<';\n+        ++dst;\n+        ++total;\n+        --size;\n+\n+        /* copy the new email */\n+        len = strlen(new_email);\n+        memcpy(dst, new_email, len);\n+        dst += len;\n+        total += len;\n+        size -= len;\n+\n+        /* copy the rest of the line */\n+        len = next - email_end;\n+        memcpy(dst, email_end, len);\n+        dst += len;\n+        total += len;\n+        size -= len;\n+\n+        return total;\n+}\n+\n+static void convert_authorcommitter(void *buffer, unsigned long size, unsigned char *result_sha1)\n+{\n+\tchar *new = xmalloc(size + 100);\n+        unsigned long newlen = 0;\n+        char *author_info = strdup(git_author_info());\n+        char *committer_info = strdup(git_committer_info());\n+        char *author_name, *author_email;\n+        char *committer_name, *committer_email;\n+        char *temp;\n+\n+//#define TESTING\n+#ifdef TESTING\n+        fprintf(stderr, \"author_info: \\\"%s\\\"\\n\",\n+                author_info);\n+        fprintf(stderr, \"committer_info: \\\"%s\\\"\\n\",\n+                committer_info);\n+#endif\n+        author_name = author_info;\n+        temp = strchr(author_name, '<');\n+        if (!temp)\n+            die(\"Unable to find valid name address.\");\n+        --temp;\n+        *temp = '\\0';\n+        temp += 2;\n+\n+        author_email = temp;\n+        temp = strrchr(author_email, '>');\n+        if (!temp)\n+            die(\"Unable to find valid email address.\");\n+        *temp = '\\0';\n+\n+        committer_name = committer_info;\n+        temp = strchr(committer_name, '<');\n+        if (!temp)\n+            die(\"Unable to find valid name address.\");\n+        --temp;\n+        *temp = '\\0';\n+        temp += 2;\n+\n+        committer_email = temp;\n+        temp = strrchr(committer_email, '>');\n+        if (!temp)\n+            die(\"Unable to find valid email address.\");\n+        *temp = '\\0';\n+\n+#ifdef TESTING\n+        fprintf(stderr, \"author_name: \\\"%s\\\"\\n\", author_name);\n+        fprintf(stderr, \"author_email: \\\"%s\\\"\\n\", author_email);\n+        fprintf(stderr, \"committer_name: \\\"%s\\\"\\n\", committer_name);\n+        fprintf(stderr, \"committer_email: \\\"%s\\\"\\n\", committer_email);\n+        exit(0);\n+#endif\n+\n+\t// \"tree <sha1>\\n\"\n+\tmemcpy(new + newlen, buffer, 46);\n+\tnewlen += 46;\n+\tbuffer += 46;\n+\tsize -= 46;\n+\n+\t// \"parent <sha1>\\n\"\n+\twhile (!memcmp(buffer, \"parent \", 7)) {\n+\t\tmemcpy(new + newlen, buffer, 48);\n+\t\tnewlen += 48;\n+\t\tbuffer += 48;\n+\t\tsize -= 48;\n+\t}\n+\n+\t// \"author xyz <xyz> date\"\n+\t// \"committer xyz <xyz> date\"\n+        newlen += convert_email_line(new + newlen, &buffer, &size, author_name, author_email);\n+        newlen += convert_email_line(new + newlen, &buffer, &size, committer_name, committer_email);\n+\n+\t// Rest\n+\tmemcpy(new + newlen, buffer, size);\n+\tnewlen += size;\n+\n+\twrite_sha1_file(new, newlen, \"commit\", result_sha1);\n+        free(new);\n+        free(author_info);\n+        free(committer_info);\n }\n \n static void convert_commit(void *buffer, unsigned long size, unsigned char *result_sha1)\n@@ -279,7 +428,117 @@ static void convert_commit(void *buffer,\n \t\tconvert_ascii_sha1(buffer+7);\n \t\tbuffer += 48;\n \t}\n-\tconvert_date(orig_buffer, orig_size, result_sha1);\n+\tconvert_authorcommitter(orig_buffer, orig_size, result_sha1);\n+}\n+\n+static void convert_tag(void *buffer, unsigned long size, unsigned char *result_sha1)\n+{\n+\tvoid *orig_buffer = buffer;\n+\n+\tchar *new = xmalloc(size + 100);\n+        unsigned long newlen = 0;\n+\n+        char *author_info = strdup(git_author_info());\n+        char *committer_info = strdup(git_committer_info());\n+        char *author_name, *author_email;\n+        char *committer_name, *committer_email;\n+        char *temp;\n+        unsigned long len = 0;\n+        char *email_start;\n+        char *email_end;\n+        char *author_start;\n+        int has_author = 1;\n+\n+        author_name = author_info;\n+        temp = strchr(author_name, '<');\n+        if (!temp)\n+            die(\"Unable to find valid name address.\");\n+        --temp;\n+        *temp = '\\0';\n+        temp += 2;\n+\n+        author_email = temp;\n+        temp = strrchr(author_email, '>');\n+        if (!temp)\n+            die(\"Unable to find valid email address.\");\n+        *temp = '\\0';\n+\n+        committer_name = committer_info;\n+        temp = strchr(committer_name, '<');\n+        if (!temp)\n+            die(\"Unable to find valid name address.\");\n+        --temp;\n+        *temp = '\\0';\n+        temp += 2;\n+\n+        committer_email = temp;\n+        temp = strrchr(committer_email, '>');\n+        if (!temp)\n+            die(\"Unable to find valid email address.\");\n+        *temp = '\\0';\n+\n+        //* START *//\n+\n+\tif (memcmp(buffer, \"object \", 7))\n+\t\tdie(\"Bad tag '%s'\", (char*) buffer);\n+        convert_ascii_sha1(buffer+7);\n+//        fprintf(stderr, \"converting %s\", (char *) (buffer + 7));\n+        buffer += 7 + 40 + 1;    /* \"object \" + \"hex sha1\" + \"\\n\" */\n+        /* type commit\n+           tag boa-0.94.14rc6\n+           tagger...\n+           */\n+        /* with tagger, we check for tagger author_name <author_email>\n+         * and if so, we convert that, too\n+         */\n+        temp = strchr(buffer, '\\n'); /* end of commit line */\n+        if (!temp) {\n+            die(\"Bad tag '%s'\", (char *) buffer);\n+        }\n+        ++temp;\n+        temp = strchr(temp, '\\n'); /* end of tag line */\n+        if (!temp) {\n+            die(\"Bad tag '%s'\", (char *) buffer);\n+        }\n+        ++temp;\n+        if (memcmp(temp, \"tagger \", 7))\n+            die(\"Bad tag '%s'\", (char *) buffer);\n+        temp += 7; /* just after 'tagger ' */\n+\n+        len = (temp - (char *) orig_buffer);\n+        memcpy(new, orig_buffer, len);\n+        newlen += len;\n+        ++temp;\n+\n+        /* check to see if the next item looks like an name + email */\n+        email_start = strchr(temp, '<');\n+        if (email_start) {\n+            email_end = strchr(email_start, '>');\n+            if (email_end) {\n+                author_start = strchr(temp, ' ');\n+                if (author_start && author_start < email_start) {\n+                    has_author = 1;\n+                    newlen += sprintf(new + newlen,\n+                                      \"%s <%s>\\n\",\n+                                      author_name,\n+                                      author_email);\n+                    len = (email_end - (char *) buffer) + 2;\n+                }\n+\n+            }\n+        }\n+\n+        if (len > size) {\n+            memcpy(new + newlen, orig_buffer + len, size - len);\n+            newlen += (size - len);\n+        }\n+//        fprintf(stderr, \"About to write: %s\", new);\n+//        exit(0);\n+\n+        write_sha1_file(new, newlen, \"tag\", result_sha1);\n+        free(new);\n+        free(author_info);\n+        free(committer_info);\n }\n \n static struct entry * convert_entry(unsigned char *sha1)\n@@ -297,13 +556,15 @@ static struct entry * convert_entry(unsi\n \n \tbuffer = xmalloc(size);\n \tmemcpy(buffer, data, size);\n-\t\n+\n \tif (!strcmp(type, \"blob\")) {\n \t\twrite_sha1_file(buffer, size, \"blob\", entry->new_sha1);\n-\t} else if (!strcmp(type, \"tree\"))\n-\t\tconvert_tree(buffer, size, entry->new_sha1);\n-\telse if (!strcmp(type, \"commit\"))\n-\t\tconvert_commit(buffer, size, entry->new_sha1);\n+        } else if (!strcmp(type, \"tree\"))\n+            convert_tree(buffer, size, entry->new_sha1);\n+        else if (!strcmp(type, \"commit\"))\n+            convert_commit(buffer, size, entry->new_sha1);\n+        else if (!strcmp(type, \"tag\"))\n+            convert_tag(buffer, size, entry->new_sha1);\n \telse\n \t\tdie(\"unknown object type '%s' in %s\", type, sha1_to_hex(sha1));\n \tentry->converted = 1;\n@@ -318,6 +579,7 @@ int main(int argc, char **argv)\n \tstruct entry *entry;\n \n \tsetup_git_directory();\n+\tsetup_ident();\n \n \tif (argc != 2 || get_sha1(argv[1], sha1))\n \t\tusage(\"git-convert-objects <sha1>\");\n"}]}