git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Karl Hasselström" <kha@treskal.com>
To: Catalin Marinas <catalin.marinas@gmail.com>
Cc: git@vger.kernel.org, "David Kågedal" <davidk@lysator.liu.se>
Subject: [StGit PATCH 1/3] Parse the date instead of treating it as an opaque string
Date: Fri, 01 Feb 2008 08:50:08 +0100	[thread overview]
Message-ID: <20080201074957.7905.52335.stgit@yoghurt> (raw)
In-Reply-To: <20080201074708.7905.98305.stgit@yoghurt>

This is needed for when we want to display it, since the
seconds-since-the-epoch format isn't that human-friendly.

Signed-off-by: Karl Hasselström <kha@treskal.com>

---

 stgit/lib/git.py |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 72 insertions(+), 4 deletions(-)


diff --git a/stgit/lib/git.py b/stgit/lib/git.py
index d75f724..50dc4f1 100644
--- a/stgit/lib/git.py
+++ b/stgit/lib/git.py
@@ -1,10 +1,17 @@
 import os, os.path, re
+from datetime import datetime, timedelta, tzinfo
+
 from stgit import exception, run, utils
 from stgit.config import config
 
 class RepositoryException(exception.StgException):
     pass
 
+class DateException(exception.StgException):
+    def __init__(self, string, type):
+        exception.StgException.__init__(
+            self, '"%s" is not a valid %s' % (string, type))
+
 class DetachedHeadException(RepositoryException):
     def __init__(self):
         RepositoryException.__init__(self, 'Not on any branch')
@@ -26,6 +33,65 @@ def make_defaults(defaults):
             return None
     return d
 
+class TimeZone(tzinfo, Repr):
+    def __init__(self, tzstring):
+        m = re.match(r'^([+-])(\d{2}):?(\d{2})$', tzstring)
+        if not m:
+            raise DateException(tzstring, 'time zone')
+        sign = int(m.group(1) + '1')
+        try:
+            self.__offset = timedelta(hours = sign*int(m.group(2)),
+                                      minutes = sign*int(m.group(3)))
+        except OverflowError:
+            raise DateException(tzstring, 'time zone')
+        self.__name = tzstring
+    def utcoffset(self, dt):
+        return self.__offset
+    def tzname(self, dt):
+        return self.__name
+    def dst(self, dt):
+        return timedelta(0)
+    def __str__(self):
+        return self.__name
+
+class Date(Repr):
+    """Immutable."""
+    def __init__(self, datestring):
+        # Try git-formatted date.
+        m = re.match(r'^(\d+)\s+([+-]\d\d:?\d\d)$', datestring)
+        if m:
+            try:
+                self.__time = datetime.fromtimestamp(int(m.group(1)),
+                                                     TimeZone(m.group(2)))
+            except ValueError:
+                raise DateException(datestring, 'date')
+            return
+
+        # Try iso-formatted date.
+        m = re.match(r'^(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})\s+'
+                     + r'([+-]\d\d:?\d\d)$', datestring)
+        if m:
+            try:
+                self.__time = datetime(
+                    *[int(m.group(i + 1)) for i in xrange(6)],
+                    **{'tzinfo': TimeZone(m.group(7))})
+            except ValueError:
+                raise DateException(datestring, 'date')
+            return
+
+        raise DateException(datestring, 'date')
+    def __str__(self):
+        return self.isoformat()
+    def isoformat(self):
+        """Human-friendly ISO 8601 format."""
+        return '%s %s' % (self.__time.replace(tzinfo = None).isoformat(' '),
+                          self.__time.tzinfo)
+    @classmethod
+    def maybe(cls, datestring):
+        if datestring in [None, NoValue]:
+            return datestring
+        return cls(datestring)
+
 class Person(Repr):
     """Immutable."""
     def __init__(self, name = NoValue, email = NoValue,
@@ -34,6 +100,7 @@ class Person(Repr):
         self.__name = d(name, 'name')
         self.__email = d(email, 'email')
         self.__date = d(date, 'date')
+        assert isinstance(self.__date, Date) or self.__date in [None, NoValue]
     name = property(lambda self: self.__name)
     email = property(lambda self: self.__email)
     date = property(lambda self: self.__date)
@@ -51,7 +118,7 @@ class Person(Repr):
         assert m
         name = m.group(1).strip()
         email = m.group(2)
-        date = m.group(3)
+        date = Date(m.group(3))
         return cls(name, email, date)
     @classmethod
     def user(cls):
@@ -65,7 +132,7 @@ class Person(Repr):
             cls.__author = cls(
                 name = os.environ.get('GIT_AUTHOR_NAME', NoValue),
                 email = os.environ.get('GIT_AUTHOR_EMAIL', NoValue),
-                date = os.environ.get('GIT_AUTHOR_DATE', NoValue),
+                date = Date.maybe(os.environ.get('GIT_AUTHOR_DATE', NoValue)),
                 defaults = cls.user())
         return cls.__author
     @classmethod
@@ -74,7 +141,8 @@ class Person(Repr):
             cls.__committer = cls(
                 name = os.environ.get('GIT_COMMITTER_NAME', NoValue),
                 email = os.environ.get('GIT_COMMITTER_EMAIL', NoValue),
-                date = os.environ.get('GIT_COMMITTER_DATE', NoValue),
+                date = Date.maybe(
+                    os.environ.get('GIT_COMMITTER_DATE', NoValue)),
                 defaults = cls.user())
         return cls.__committer
 
@@ -301,7 +369,7 @@ class Repository(RunWithEnv):
                 for attr, v2 in (('name', 'NAME'), ('email', 'EMAIL'),
                                  ('date', 'DATE')):
                     if getattr(p, attr) != None:
-                        env['GIT_%s_%s' % (v1, v2)] = getattr(p, attr)
+                        env['GIT_%s_%s' % (v1, v2)] = str(getattr(p, attr))
         sha1 = self.run(c, env = env).raw_input(commitdata.message
                                                 ).output_one_line()
         return self.get_commit(sha1)

  reply	other threads:[~2008-02-01  7:53 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-29  2:58 kha/safe and kha/experimental updated Karl Hasselström
2008-01-29  3:02 ` [StGit PATCH 0/5] Various cleanups Karl Hasselström
2008-01-29  3:02   ` [StGit PATCH 1/5] Create index and worktree objects just once Karl Hasselström
2008-01-29  3:03   ` [StGit PATCH 2/5] Wrap excessively long line Karl Hasselström
2008-01-29  3:03   ` [StGit PATCH 3/5] Eliminate temp variable that's used just once Karl Hasselström
2008-01-29  3:04   ` [StGit PATCH 4/5] Simplify editor selection logic Karl Hasselström
2008-01-29 20:09     ` Peter Oberndorfer
2008-01-30  7:28       ` Karl Hasselström
2008-01-30 14:55         ` Jay Soffian
2008-01-30 17:57           ` Karl Hasselström
2008-01-29  3:06   ` [StGit PATCH 5/5] Let the caller supply the diff text to diffstat() Karl Hasselström
2008-01-29  3:10 ` [StGit PATCH 0/2] "stg clean" test+bugfix Karl Hasselström
2008-01-29  3:11   ` [StGit PATCH 1/2] Add test to ensure that "stg clean" preserves conflicting patches Karl Hasselström
2008-01-29  3:12   ` [StGit PATCH 2/2] Don't clean away patches with conflicts Karl Hasselström
2008-01-29  3:15 ` [StGit PATCH 0/4] Rewrite "stg edit" to use new infrastructure Karl Hasselström
2008-01-29  3:15   ` [StGit PATCH 1/4] Teach new infrastructure about the default author and committer Karl Hasselström
2008-01-29  3:15   ` [StGit PATCH 2/4] Teach new infrastructure to apply patches Karl Hasselström
2008-01-29  3:16   ` [StGit PATCH 3/4] Teach new infrastructure to diff two trees Karl Hasselström
2008-01-29 14:40     ` David Kågedal
2008-01-29 15:57       ` Karl Hasselström
2008-01-29  3:17   ` [StGit PATCH 4/4] Convert "stg edit" to the new infrastructure Karl Hasselström
2008-02-01  7:49   ` [StGit PATCH 0/3] "stg edit" fixups Karl Hasselström
2008-02-01  7:50     ` Karl Hasselström [this message]
2008-02-01  7:50     ` [StGit PATCH 2/3] Convert "stg edit" to the new infrastructure Karl Hasselström
2008-02-01  7:50     ` [StGit PATCH 3/3] It's possible to edit unapplied patches now Karl Hasselström

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=20080201074957.7905.52335.stgit@yoghurt \
    --to=kha@treskal.com \
    --cc=catalin.marinas@gmail.com \
    --cc=davidk@lysator.liu.se \
    --cc=git@vger.kernel.org \
    /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).