{"thread":{"id":"31832","subject":"[PATCH v3] git-cvsimport: allow author-specific timezones","startedAt":"2012-10-16T02:40:53Z","lastAt":"2012-10-16T02:40:53Z","messageCount":1,"participants":["Chris Rorvick"],"isPatch":true,"patchVersion":3,"patchTotal":null},"messages":[{"id":"201306","messageId":"1350355253-311-1-git-send-email-chris@rorvick.com","threadId":"31832","inReplyTo":null,"subject":"[PATCH v3] git-cvsimport: allow author-specific timezones","fromName":"Chris Rorvick","fromEmail":"chris@rorvick.com","sentAt":"2012-10-16T02:40:53Z","receivedAt":"2012-10-16T02:40:53Z","isPatch":true,"sender":{"key":"chris@rorvick.com","avatar":"https://avatars.githubusercontent.com/u/824726?v=4"},"body":"CVS patchsets are imported with timestamps having an offset of +0000\n(UTC).  The cvs-authors file is already used to translate the CVS\nusername to full name and email in the corresponding commit.  Extend\nthis file to support an optional timezone for calculating a user-\nspecific timestamp offset.\n\nSigned-off-by: Chris Rorvick <chris@rorvick.com>\n---\n\nCleaned up unit tests and added more detail to documentation.\n\nUnit test is inherently platform dependent due to dependency on\nzoneinfo database.  Is there a way to improve this situation?\n\n Documentation/git-cvsimport.txt    |   8 +-\n git-cvsimport.perl                 |  22 ++-\n t/t9604-cvsimport-timestamps.sh    |  71 ++++++++++\n t/t9604/cvsroot/.gitattributes     |   1 +\n t/t9604/cvsroot/CVSROOT/.gitignore |   2 +\n t/t9604/cvsroot/module/a,v         | 265 +++++++++++++++++++++++++++++++++++++\n 6 files changed, 362 insertions(+), 7 deletions(-)\n create mode 100755 t/t9604-cvsimport-timestamps.sh\n create mode 100644 t/t9604/cvsroot/.gitattributes\n create mode 100644 t/t9604/cvsroot/CVSROOT/.gitignore\n create mode 100644 t/t9604/cvsroot/module/a,v\n\ndiff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt\nindex 6695ab3..9ea8bb5 100644\n--- a/Documentation/git-cvsimport.txt\n+++ b/Documentation/git-cvsimport.txt\n@@ -137,17 +137,19 @@ This option can be used several times to provide several detection regexes.\n -A <author-conv-file>::\n \tCVS by default uses the Unix username when writing its\n \tcommit logs. Using this option and an author-conv-file\n-\tin this format\n+\tmaps the name recorded in CVS to author name, e-mail and\n+\tand optional timezone:\n +\n ---------\n \texon=Andreas Ericsson <ae@op5.se>\n-\tspawn=Simon Pawn <spawn@frog-pond.org>\n+\tspawn=Simon Pawn <spawn@frog-pond.org> America/Chicago\n \n ---------\n +\n 'git cvsimport' will make it appear as those authors had\n their GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL set properly\n-all along.\n+all along.  If a timezone is specified, GIT_AUTHOR_DATE will\n+have the corresponding offset applied.\n +\n For convenience, this data is saved to `$GIT_DIR/cvs-authors`\n each time the '-A' option is provided and read from that same\ndiff --git a/git-cvsimport.perl b/git-cvsimport.perl\nindex 8032f23..ceb119d 100755\n--- a/git-cvsimport.perl\n+++ b/git-cvsimport.perl\n@@ -31,7 +31,7 @@ $SIG{'PIPE'}=\"IGNORE\";\n $ENV{'TZ'}=\"UTC\";\n \n our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,@opt_M,$opt_A,$opt_S,$opt_L, $opt_a, $opt_r, $opt_R);\n-my (%conv_author_name, %conv_author_email);\n+my (%conv_author_name, %conv_author_email, %conv_author_tz);\n \n sub usage(;$) {\n \tmy $msg = shift;\n@@ -59,6 +59,14 @@ sub read_author_info($) {\n \t\t\t$conv_author_name{$user} = $2;\n \t\t\t$conv_author_email{$user} = $3;\n \t\t}\n+\t\t# or with an optional timezone:\n+\t\t#   spawn=Simon Pawn <spawn@frog-pond.org> America/Chicago\n+\t\telsif (m/^(\\S+?)\\s*=\\s*(.+?)\\s*<(.+)>\\s*(\\S+?)\\s*$/) {\n+\t\t\t$user = $1;\n+\t\t\t$conv_author_name{$user} = $2;\n+\t\t\t$conv_author_email{$user} = $3;\n+\t\t\t$conv_author_tz{$user} = $4;\n+\t\t}\n \t\t# However, we also read from CVSROOT/users format\n \t\t# to ease migration.\n \t\telsif (/^(\\w+):(['\"]?)(.+?)\\2\\s*$/) {\n@@ -84,7 +92,9 @@ sub write_author_info($) {\n \t  die(\"Failed to open $file for writing: $!\");\n \n \tforeach (keys %conv_author_name) {\n-\t\tprint $f \"$_=$conv_author_name{$_} <$conv_author_email{$_}>\\n\";\n+\t\tprint $f \"$_=$conv_author_name{$_} <$conv_author_email{$_}>\";\n+\t\tprint $f \" $conv_author_tz{$_}\" if ($conv_author_tz{$_});\n+\t\tprint $f \"\\n\";\n \t}\n \tclose ($f);\n }\n@@ -795,7 +805,7 @@ sub write_tree () {\n \treturn $tree;\n }\n \n-my ($patchset,$date,$author_name,$author_email,$branch,$ancestor,$tag,$logmsg);\n+my ($patchset,$date,$author_name,$author_email,$author_tz,$branch,$ancestor,$tag,$logmsg);\n my (@old,@new,@skipped,%ignorebranch,@commit_revisions);\n \n # commits that cvsps cannot place anywhere...\n@@ -844,7 +854,9 @@ sub commit {\n \t\t}\n \t}\n \n-\tmy $commit_date = strftime(\"+0000 %Y-%m-%d %H:%M:%S\",gmtime($date));\n+\t$ENV{'TZ'}=$author_tz;\n+\tmy $commit_date = strftime(\"%s %z\", localtime($date));\n+\t$ENV{'TZ'}=\"UTC\";\n \t$ENV{GIT_AUTHOR_NAME} = $author_name;\n \t$ENV{GIT_AUTHOR_EMAIL} = $author_email;\n \t$ENV{GIT_AUTHOR_DATE} = $commit_date;\n@@ -945,12 +957,14 @@ while (<CVS>) {\n \t\t}\n \t\t$state=3;\n \t} elsif ($state == 3 and s/^Author:\\s+//) {\n+\t\t$author_tz = \"UTC\";\n \t\ts/\\s+$//;\n \t\tif (/^(.*?)\\s+<(.*)>/) {\n \t\t    ($author_name, $author_email) = ($1, $2);\n \t\t} elsif ($conv_author_name{$_}) {\n \t\t\t$author_name = $conv_author_name{$_};\n \t\t\t$author_email = $conv_author_email{$_};\n+\t\t\t$author_tz = $conv_author_tz{$_} if ($conv_author_tz{$_});\n \t\t} else {\n \t\t    $author_name = $author_email = $_;\n \t\t}\ndiff --git a/t/t9604-cvsimport-timestamps.sh b/t/t9604-cvsimport-timestamps.sh\nnew file mode 100755\nindex 0000000..7e2fe2c\n--- /dev/null\n+++ b/t/t9604-cvsimport-timestamps.sh\n@@ -0,0 +1,71 @@\n+#!/bin/sh\n+\n+test_description='git cvsimport timestamps'\n+. ./lib-cvs.sh\n+\n+setup_cvs_test_repository t9604\n+\n+test_expect_success 'check timestamps are UTC (TZ=America/Chicago)' '\n+\n+\tTZ=America/Chicago git cvsimport -p\"-x\" -C module-1 module &&\n+\tgit cvsimport -p\"-x\" -C module-1 module &&\n+\t(\n+\t\tcd module-1 &&\n+\t\tgit log --format=\"%s %ai\"\n+\t) >actual-1 &&\n+\tcat >expect-1 <<-EOF &&\n+\tRev 16 2011-11-06 07:00:01 +0000\n+\tRev 15 2011-11-06 06:59:59 +0000\n+\tRev 14 2011-03-13 08:00:01 +0000\n+\tRev 13 2011-03-13 07:59:59 +0000\n+\tRev 12 2010-12-01 00:00:00 +0000\n+\tRev 11 2010-11-01 00:00:00 +0000\n+\tRev 10 2010-10-01 00:00:00 +0000\n+\tRev  9 2010-09-01 00:00:00 +0000\n+\tRev  8 2010-08-01 00:00:00 +0000\n+\tRev  7 2010-07-01 00:00:00 +0000\n+\tRev  6 2010-06-01 00:00:00 +0000\n+\tRev  5 2010-05-01 00:00:00 +0000\n+\tRev  4 2010-04-01 00:00:00 +0000\n+\tRev  3 2010-03-01 00:00:00 +0000\n+\tRev  2 2010-02-01 00:00:00 +0000\n+\tRev  1 2010-01-01 00:00:00 +0000\n+\tEOF\n+\ttest_cmp actual-1 expect-1\n+'\n+\n+test_expect_success 'check timestamps with author-specific timezones' '\n+\n+\tcat >cvs-authors <<-EOF &&\n+\tuser1=User One <user1@domain.org>\n+\tuser2=User Two <user2@domain.org> America/Chicago\n+\tuser3=User Three <user3@domain.org> Australia/Sydney\n+\tuser4=User Four <user4@domain.org> Asia/Shanghai\n+\tEOF\n+\tgit cvsimport -p\"-x\" -A cvs-authors -C module-2 module &&\n+\t(\n+\t\tcd module-2 &&\n+\t\tgit log --format=\"%s %ai %an\"\n+\t) >actual-2 &&\n+\tcat >expect-2 <<-EOF &&\n+\tRev 16 2011-11-06 01:00:01 -0600 User Two\n+\tRev 15 2011-11-06 01:59:59 -0500 User Two\n+\tRev 14 2011-03-13 03:00:01 -0500 User Two\n+\tRev 13 2011-03-13 01:59:59 -0600 User Two\n+\tRev 12 2010-12-01 08:00:00 +0800 User Four\n+\tRev 11 2010-11-01 11:00:00 +1100 User Three\n+\tRev 10 2010-09-30 19:00:00 -0500 User Two\n+\tRev  9 2010-09-01 00:00:00 +0000 User One\n+\tRev  8 2010-08-01 08:00:00 +0800 User Four\n+\tRev  7 2010-07-01 10:00:00 +1000 User Three\n+\tRev  6 2010-05-31 19:00:00 -0500 User Two\n+\tRev  5 2010-05-01 00:00:00 +0000 User One\n+\tRev  4 2010-04-01 08:00:00 +0800 User Four\n+\tRev  3 2010-03-01 11:00:00 +1100 User Three\n+\tRev  2 2010-01-31 18:00:00 -0600 User Two\n+\tRev  1 2010-01-01 00:00:00 +0000 User One\n+\tEOF\n+\ttest_cmp actual-2 expect-2\n+'\n+\n+test_done\ndiff --git a/t/t9604/cvsroot/.gitattributes b/t/t9604/cvsroot/.gitattributes\nnew file mode 100644\nindex 0000000..562b12e\n--- /dev/null\n+++ b/t/t9604/cvsroot/.gitattributes\n@@ -0,0 +1 @@\n+* -whitespace\ndiff --git a/t/t9604/cvsroot/CVSROOT/.gitignore b/t/t9604/cvsroot/CVSROOT/.gitignore\nnew file mode 100644\nindex 0000000..3bb9b34\n--- /dev/null\n+++ b/t/t9604/cvsroot/CVSROOT/.gitignore\n@@ -0,0 +1,2 @@\n+history\n+val-tags\ndiff --git a/t/t9604/cvsroot/module/a,v b/t/t9604/cvsroot/module/a,v\nnew file mode 100644\nindex 0000000..7165de7\n--- /dev/null\n+++ b/t/t9604/cvsroot/module/a,v\n@@ -0,0 +1,265 @@\n+head\t1.16;\n+access;\n+symbols;\n+locks; strict;\n+comment\t@# @;\n+\n+\n+1.16\n+date\t2011.11.06.07.00.01;\tauthor user2;\tstate Exp;\n+branches;\n+next\t1.15;\n+\n+1.15\n+date\t2011.11.06.06.59.59;\tauthor user2;\tstate Exp;\n+branches;\n+next\t1.14;\n+\n+1.14\n+date\t2011.03.13.08.00.01;\tauthor user2;\tstate Exp;\n+branches;\n+next\t1.13;\n+\n+1.13\n+date\t2011.03.13.07.59.59;\tauthor user2;\tstate Exp;\n+branches;\n+next\t1.12;\n+\n+1.12\n+date\t2010.12.01.00.00.00;\tauthor user4;\tstate Exp;\n+branches;\n+next\t1.11;\n+\n+1.11\n+date\t2010.11.01.00.00.00;\tauthor user3;\tstate Exp;\n+branches;\n+next\t1.10;\n+\n+1.10\n+date\t2010.10.01.00.00.00;\tauthor user2;\tstate Exp;\n+branches;\n+next\t1.9;\n+\n+1.9\n+date\t2010.09.01.00.00.00;\tauthor user1;\tstate Exp;\n+branches;\n+next\t1.8;\n+\n+1.8\n+date\t2010.08.01.00.00.00;\tauthor user4;\tstate Exp;\n+branches;\n+next\t1.7;\n+\n+1.7\n+date\t2010.07.01.00.00.00;\tauthor user3;\tstate Exp;\n+branches;\n+next\t1.6;\n+\n+1.6\n+date\t2010.06.01.00.00.00;\tauthor user2;\tstate Exp;\n+branches;\n+next\t1.5;\n+\n+1.5\n+date\t2010.05.01.00.00.00;\tauthor user1;\tstate Exp;\n+branches;\n+next\t1.4;\n+\n+1.4\n+date\t2010.04.01.00.00.00;\tauthor user4;\tstate Exp;\n+branches;\n+next\t1.3;\n+\n+1.3\n+date\t2010.03.01.00.00.00;\tauthor user3;\tstate Exp;\n+branches;\n+next\t1.2;\n+\n+1.2\n+date\t2010.02.01.00.00.00;\tauthor user2;\tstate Exp;\n+branches;\n+next\t1.1;\n+\n+1.1\n+date\t2010.01.01.00.00.00;\tauthor user1;\tstate Exp;\n+branches;\n+next\t;\n+\n+\n+desc\n+@@\n+\n+\n+1.16\n+log\n+@Rev 16\n+@\n+text\n+@Rev 16\n+@\n+\n+\n+1.15\n+log\n+@Rev 15\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 15\n+@\n+\n+\n+1.14\n+log\n+@Rev 14\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 14\n+@\n+\n+\n+1.13\n+log\n+@Rev 13\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 13\n+@\n+\n+\n+1.12\n+log\n+@Rev 12\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 12\n+@\n+\n+\n+1.11\n+log\n+@Rev 11\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 11\n+@\n+\n+\n+1.10\n+log\n+@Rev 10\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 10\n+@\n+\n+\n+1.9\n+log\n+@Rev  9\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 9\n+@\n+\n+\n+1.8\n+log\n+@Rev  8\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 8\n+@\n+\n+\n+1.7\n+log\n+@Rev  7\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 7\n+@\n+\n+\n+1.6\n+log\n+@Rev  6\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 6\n+@\n+\n+\n+1.5\n+log\n+@Rev  5\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 5\n+@\n+\n+\n+1.4\n+log\n+@Rev  4\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 4\n+@\n+\n+\n+1.3\n+log\n+@Rev  3\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 3\n+@\n+\n+\n+1.2\n+log\n+@Rev  2\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 2\n+@\n+\n+\n+1.1\n+log\n+@Rev  1\n+@\n+text\n+@d1 1\n+a1 1\n+Rev 1\n+@\n+\n-- \n1.8.0.rc1.19.gbecacc0\n"}]}