git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Fix a portability issue with git-cvsimport
@ 2013-02-09 21:46 Ben Walton
  2013-02-09 21:46 ` [PATCH 1/3] Move Git::SVN::get_tz to Git::get_tz_offset Ben Walton
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Ben Walton @ 2013-02-09 21:46 UTC (permalink / raw)
  To: gitster; +Cc: git, Ben Walton

This is my (long overdue) re-roll of the series that fixes a
portability issue with git-cvsimport's use of strftime.  It also fixes
a but in the original implementation of get_tz (now get_tz_offset).

I ended up taking taking only part of the implementation suggested by
Junio.

The only usage of get_tz_offset is by git-cvsimport and Git::SVN::Log
currently.  There are tests that validate it works currently so I
didn't add anything additional.  If the git-cvsimport tests are
removed, there are no tests remaining that exercise the code full as
the SVN tests use UTC times.

Ben Walton (3):
  Move Git::SVN::get_tz to Git::get_tz_offset
  Fix get_tz_offset to properly handle DST boundary cases
  Avoid non-portable strftime format specifiers in git-cvsimport

 git-cvsimport.perl  |    5 ++++-
 perl/Git.pm         |   23 +++++++++++++++++++++++
 perl/Git/SVN.pm     |   12 ++----------
 perl/Git/SVN/Log.pm |    8 ++++++--
 4 files changed, 35 insertions(+), 13 deletions(-)

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] Move Git::SVN::get_tz to Git::get_tz_offset
  2013-02-09 21:46 [PATCH 0/3] Fix a portability issue with git-cvsimport Ben Walton
@ 2013-02-09 21:46 ` Ben Walton
  2013-02-09 21:46 ` [PATCH 2/3] Fix get_tz_offset to properly handle DST boundary cases Ben Walton
  2013-02-09 21:46 ` [PATCH 3/3] Avoid non-portable strftime format specifiers in git-cvsimport Ben Walton
  2 siblings, 0 replies; 6+ messages in thread
From: Ben Walton @ 2013-02-09 21:46 UTC (permalink / raw)
  To: gitster; +Cc: git, Ben Walton

This function has utility outside of the SVN module for any routine
that needs the equivalent of GNU strftime's %z formatting option.
Move it to the top-level Git.pm so that non-SVN modules don't need to
import the SVN module to use it.

The rename makes the purpose of the function clearer.

Signed-off-by: Ben Walton <bdwalton@gmail.com>
---
 perl/Git.pm         |   23 +++++++++++++++++++++++
 perl/Git/SVN.pm     |   12 ++----------
 perl/Git/SVN/Log.pm |    8 ++++++--
 3 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/perl/Git.pm b/perl/Git.pm
index 931047c..5649bcc 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -59,6 +59,7 @@ require Exporter;
                 command_bidi_pipe command_close_bidi_pipe
                 version exec_path html_path hash_object git_cmd_try
                 remote_refs prompt
+                get_tz_offset
                 temp_acquire temp_release temp_reset temp_path);
 
 
@@ -102,6 +103,7 @@ use Error qw(:try);
 use Cwd qw(abs_path cwd);
 use IPC::Open2 qw(open2);
 use Fcntl qw(SEEK_SET SEEK_CUR);
+use Time::Local qw(timelocal);
 }
 
 
@@ -511,6 +513,27 @@ C<git --html-path>). Useful mostly only internally.
 
 sub html_path { command_oneline('--html-path') }
 
+
+=item get_tz_offset ( TIME )
+
+Return the time zone offset from GMT in the form +/-HHMM where HH is
+the number of hours from GMT and MM is the number of minutes.  This is
+the equivalent of what strftime("%z", ...) would provide on a GNU
+platform.
+
+If TIME is not supplied, the current local time is used.
+
+=cut
+
+sub get_tz_offset {
+	# some systmes don't handle or mishandle %z, so be creative.
+	my $t = shift || time;
+	my $gm = timelocal(gmtime($t));
+	my $sign = qw( + + - )[ $t <=> $gm ];
+	return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
+}
+
+
 =item prompt ( PROMPT , ISPASSWORD  )
 
 Query user C<PROMPT> and return answer from user.
diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm
index 490e330..0ebc68a 100644
--- a/perl/Git/SVN.pm
+++ b/perl/Git/SVN.pm
@@ -11,7 +11,6 @@ use Carp qw/croak/;
 use File::Path qw/mkpath/;
 use File::Copy qw/copy/;
 use IPC::Open3;
-use Time::Local;
 use Memoize;  # core since 5.8.0, Jul 2002
 use Memoize::Storable;
 use POSIX qw(:signal_h);
@@ -22,6 +21,7 @@ use Git qw(
     command_noisy
     command_output_pipe
     command_close_pipe
+    get_tz_offset
 );
 use Git::SVN::Utils qw(
 	fatal
@@ -1311,14 +1311,6 @@ sub get_untracked {
 	\@out;
 }
 
-sub get_tz {
-	# some systmes don't handle or mishandle %z, so be creative.
-	my $t = shift || time;
-	my $gm = timelocal(gmtime($t));
-	my $sign = qw( + + - )[ $t <=> $gm ];
-	return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
-}
-
 # parse_svn_date(DATE)
 # --------------------
 # Given a date (in UTC) from Subversion, return a string in the format
@@ -1351,7 +1343,7 @@ sub parse_svn_date {
 			delete $ENV{TZ};
 		}
 
-		my $our_TZ = get_tz();
+		my $our_TZ = get_tz_offset();
 
 		# This converts $epoch_in_UTC into our local timezone.
 		my ($sec, $min, $hour, $mday, $mon, $year,
diff --git a/perl/Git/SVN/Log.pm b/perl/Git/SVN/Log.pm
index 3cc1c6f..3f8350a 100644
--- a/perl/Git/SVN/Log.pm
+++ b/perl/Git/SVN/Log.pm
@@ -2,7 +2,11 @@ package Git::SVN::Log;
 use strict;
 use warnings;
 use Git::SVN::Utils qw(fatal);
-use Git qw(command command_oneline command_output_pipe command_close_pipe);
+use Git qw(command
+           command_oneline
+           command_output_pipe
+           command_close_pipe
+           get_tz_offset);
 use POSIX qw/strftime/;
 use constant commit_log_separator => ('-' x 72) . "\n";
 use vars qw/$TZ $limit $color $pager $non_recursive $verbose $oneline
@@ -119,7 +123,7 @@ sub run_pager {
 sub format_svn_date {
 	my $t = shift || time;
 	require Git::SVN;
-	my $gmoff = Git::SVN::get_tz($t);
+	my $gmoff = get_tz_offset($t);
 	return strftime("%Y-%m-%d %H:%M:%S $gmoff (%a, %d %b %Y)", localtime($t));
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] Fix get_tz_offset to properly handle DST boundary cases
  2013-02-09 21:46 [PATCH 0/3] Fix a portability issue with git-cvsimport Ben Walton
  2013-02-09 21:46 ` [PATCH 1/3] Move Git::SVN::get_tz to Git::get_tz_offset Ben Walton
@ 2013-02-09 21:46 ` Ben Walton
  2013-02-09 22:58   ` Junio C Hamano
  2013-02-09 21:46 ` [PATCH 3/3] Avoid non-portable strftime format specifiers in git-cvsimport Ben Walton
  2 siblings, 1 reply; 6+ messages in thread
From: Ben Walton @ 2013-02-09 21:46 UTC (permalink / raw)
  To: gitster; +Cc: git, Ben Walton

When passed a local time that was on the boundary of a DST change,
get_tz_offset returned a GMT offset that was incorrect (off by one
hour).  This is because the time was converted to GMT and then back to
a time stamp via timelocal() which cannot disambiguate boundary cases
as noted in its documentation.

Modify this algorithm, using an approach suggested by Junio C Hamano
that obtains the GMT time stamp by using timegm(localtime()) instead
of timelocal(gmtime()).  This avoids the ambigious conversion and
allows a correct time to be returned on every occassion.

Signed-off-by: Ben Walton <bdwalton@gmail.com>
---
 perl/Git.pm |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/perl/Git.pm b/perl/Git.pm
index 5649bcc..a56d1e7 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -103,7 +103,7 @@ use Error qw(:try);
 use Cwd qw(abs_path cwd);
 use IPC::Open2 qw(open2);
 use Fcntl qw(SEEK_SET SEEK_CUR);
-use Time::Local qw(timelocal);
+use Time::Local qw(timegm);
 }
 
 
@@ -528,8 +528,8 @@ If TIME is not supplied, the current local time is used.
 sub get_tz_offset {
 	# some systmes don't handle or mishandle %z, so be creative.
 	my $t = shift || time;
-	my $gm = timelocal(gmtime($t));
-	my $sign = qw( + + - )[ $t <=> $gm ];
+	my $gm = timegm(localtime($t));
+	my $sign = qw( + + - )[ $gm <=> $t ];
 	return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
 }
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] Avoid non-portable strftime format specifiers in git-cvsimport
  2013-02-09 21:46 [PATCH 0/3] Fix a portability issue with git-cvsimport Ben Walton
  2013-02-09 21:46 ` [PATCH 1/3] Move Git::SVN::get_tz to Git::get_tz_offset Ben Walton
  2013-02-09 21:46 ` [PATCH 2/3] Fix get_tz_offset to properly handle DST boundary cases Ben Walton
@ 2013-02-09 21:46 ` Ben Walton
  2013-02-09 22:20   ` Junio C Hamano
  2 siblings, 1 reply; 6+ messages in thread
From: Ben Walton @ 2013-02-09 21:46 UTC (permalink / raw)
  To: gitster; +Cc: git, Ben Walton

Neither %s or %z are portable strftime format specifiers.  There is no
need for %s in git-cvsimport as the supplied time is already in
seconds since the epoch.  For %z, use the function get_tz_offset
provided by Git.pm instead.

Signed-off-by: Ben Walton <bdwalton@gmail.com>
---
 git-cvsimport.perl |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index 0a31ebd..344f120 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -26,6 +26,7 @@ use IO::Socket;
 use IO::Pipe;
 use POSIX qw(strftime tzset dup2 ENOENT);
 use IPC::Open2;
+use Git qw(get_tz_offset);
 
 $SIG{'PIPE'}="IGNORE";
 set_timezone('UTC');
@@ -864,7 +865,9 @@ sub commit {
 	}
 
 	set_timezone($author_tz);
-	my $commit_date = strftime("%s %z", localtime($date));
+	# $date is in the seconds since epoch format
+	my $tz_offset = get_tz_offset($date);
+	my $commit_date = "$date $tz_offset";
 	set_timezone('UTC');
 	$ENV{GIT_AUTHOR_NAME} = $author_name;
 	$ENV{GIT_AUTHOR_EMAIL} = $author_email;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3] Avoid non-portable strftime format specifiers in git-cvsimport
  2013-02-09 21:46 ` [PATCH 3/3] Avoid non-portable strftime format specifiers in git-cvsimport Ben Walton
@ 2013-02-09 22:20   ` Junio C Hamano
  0 siblings, 0 replies; 6+ messages in thread
From: Junio C Hamano @ 2013-02-09 22:20 UTC (permalink / raw)
  To: Ben Walton; +Cc: git

Ben Walton <bdwalton@gmail.com> writes:

> Neither %s or %z are portable strftime format specifiers.

Well, at least %z is in POSIX; "Some implementations of strftime(3)
lack support for %z format" is fine, tough.

Thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/3] Fix get_tz_offset to properly handle DST boundary cases
  2013-02-09 21:46 ` [PATCH 2/3] Fix get_tz_offset to properly handle DST boundary cases Ben Walton
@ 2013-02-09 22:58   ` Junio C Hamano
  0 siblings, 0 replies; 6+ messages in thread
From: Junio C Hamano @ 2013-02-09 22:58 UTC (permalink / raw)
  To: Ben Walton; +Cc: git

Ben Walton <bdwalton@gmail.com> writes:

> When passed a local time that was on the boundary of a DST change,
> get_tz_offset returned a GMT offset that was incorrect (off by one
> hour).  This is because the time was converted to GMT and then back to
> a time stamp via timelocal() which cannot disambiguate boundary cases
> as noted in its documentation.
>
> Modify this algorithm, using an approach suggested by Junio C Hamano
> that obtains the GMT time stamp by using timegm(localtime()) instead
> of timelocal(gmtime()).  This avoids the ambigious conversion and
> allows a correct time to be returned on every occassion.

I'll reword the log message a bit to explain why the updated logic
is right and also refer to the message that has the suggestion.  o

The implemmentation is a bit dense to my taste, but looks correct (I
had to think about the comparison to come up with the value of the
$sign, though).

Thanks.

> Signed-off-by: Ben Walton <bdwalton@gmail.com>
> ---
>  perl/Git.pm |    6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/perl/Git.pm b/perl/Git.pm
> index 5649bcc..a56d1e7 100644
> --- a/perl/Git.pm
> +++ b/perl/Git.pm
> @@ -103,7 +103,7 @@ use Error qw(:try);
>  use Cwd qw(abs_path cwd);
>  use IPC::Open2 qw(open2);
>  use Fcntl qw(SEEK_SET SEEK_CUR);
> -use Time::Local qw(timelocal);
> +use Time::Local qw(timegm);
>  }
>  
>  
> @@ -528,8 +528,8 @@ If TIME is not supplied, the current local time is used.
>  sub get_tz_offset {
>  	# some systmes don't handle or mishandle %z, so be creative.
>  	my $t = shift || time;
> -	my $gm = timelocal(gmtime($t));
> -	my $sign = qw( + + - )[ $t <=> $gm ];
> +	my $gm = timegm(localtime($t));
> +	my $sign = qw( + + - )[ $gm <=> $t ];
>  	return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
>  }

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-02-09 22:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-02-09 21:46 [PATCH 0/3] Fix a portability issue with git-cvsimport Ben Walton
2013-02-09 21:46 ` [PATCH 1/3] Move Git::SVN::get_tz to Git::get_tz_offset Ben Walton
2013-02-09 21:46 ` [PATCH 2/3] Fix get_tz_offset to properly handle DST boundary cases Ben Walton
2013-02-09 22:58   ` Junio C Hamano
2013-02-09 21:46 ` [PATCH 3/3] Avoid non-portable strftime format specifiers in git-cvsimport Ben Walton
2013-02-09 22:20   ` Junio C Hamano

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).