Move cache message to directory creation.
[jelmer/subvertpy.git] / repository.py
index 79f3d0a60629563d23399d93a7b9323b10637dde..2b0af5471abecf1c9d1a7e619bce4b8c917584fd 100644 (file)
@@ -39,178 +39,18 @@ import calendar
 from config import SvnRepositoryConfig
 import errors
 import logwalker
-from mapping import default_mapping
-from revids import (MAPPING_VERSION, RevidMap)
+from mapping import (default_mapping, SVN_PROP_BZR_REVISION_ID, 
+                     SVN_PROP_BZR_REVISION_INFO, SVN_PROP_BZR_BRANCHING_SCHEME,
+                     SVN_PROP_BZR_ANCESTRY, SVN_PROP_BZR_FILEIDS,
+                     parse_revision_metadata, parse_revid_property)
+                      
+from revids import RevidMap
 from scheme import (BranchingScheme, ListBranchingScheme, 
                     parse_list_scheme_text, guess_scheme_from_history)
 from tree import SvnRevisionTree
-import time
 import urllib
 
-SVN_PROP_BZR_PREFIX = 'bzr:'
-SVN_PROP_BZR_ANCESTRY = 'bzr:ancestry:v%d-' % MAPPING_VERSION
-SVN_PROP_BZR_FILEIDS = 'bzr:file-ids'
-SVN_PROP_BZR_MERGE = 'bzr:merge'
 SVN_PROP_SVK_MERGE = 'svk:merge'
-SVN_PROP_BZR_REVISION_INFO = 'bzr:revision-info'
-SVN_PROP_BZR_REVISION_ID = 'bzr:revision-id:v%d-' % MAPPING_VERSION
-SVN_PROP_BZR_BRANCHING_SCHEME = 'bzr:branching-scheme'
-
-SVN_REVPROP_BZR_COMMITTER = 'bzr:committer'
-SVN_REVPROP_BZR_FILEIDS = 'bzr:file-ids'
-SVN_REVPROP_BZR_MERGE = 'bzr:merge'
-SVN_REVPROP_BZR_REVISION_ID = 'bzr:revision-id'
-SVN_REVPROP_BZR_REVPROP_PREFIX = 'bzr:revprop:'
-SVN_REVPROP_BZR_ROOT = 'bzr:root'
-SVN_REVPROP_BZR_SCHEME = 'bzr:scheme'
-SVN_REVPROP_BZR_SIGNATURE = 'bzr:gpg-signature'
-
-# The following two functions don't use day names (which can vary by 
-# locale) unlike the alternatives in bzrlib.timestamp
-
-def format_highres_date(t, offset=0):
-    """Format a date, such that it includes higher precision in the
-    seconds field.
-
-    :param t:   The local time in fractional seconds since the epoch
-    :type t: float
-    :param offset:  The timezone offset in integer seconds
-    :type offset: int
-    """
-    assert isinstance(t, float)
-
-    # This has to be formatted for "original" date, so that the
-    # revision XML entry will be reproduced faithfully.
-    if offset is None:
-        offset = 0
-    tt = time.gmtime(t + offset)
-
-    return (time.strftime("%Y-%m-%d %H:%M:%S", tt)
-            # Get the high-res seconds, but ignore the 0
-            + ('%.9f' % (t - int(t)))[1:]
-            + ' %+03d%02d' % (offset / 3600, (offset / 60) % 60))
-
-
-def unpack_highres_date(date):
-    """This takes the high-resolution date stamp, and
-    converts it back into the tuple (timestamp, timezone)
-    Where timestamp is in real UTC since epoch seconds, and timezone is an
-    integer number of seconds offset.
-
-    :param date: A date formated by format_highres_date
-    :type date: string
-    """
-    # skip day if applicable
-    if not date[0].isdigit():
-        space_loc = date.find(' ')
-        if space_loc == -1:
-            raise ValueError("No valid date: %r" % date)
-        date = date[space_loc+1:]
-    # Up until the first period is a datestamp that is generated
-    # as normal from time.strftime, so use time.strptime to
-    # parse it
-    dot_loc = date.find('.')
-    if dot_loc == -1:
-        raise ValueError(
-            'Date string does not contain high-precision seconds: %r' % date)
-    base_time = time.strptime(date[:dot_loc], "%Y-%m-%d %H:%M:%S")
-    fract_seconds, offset = date[dot_loc:].split()
-    fract_seconds = float(fract_seconds)
-
-    offset = int(offset)
-
-    hours = int(offset / 100)
-    minutes = (offset % 100)
-    seconds_offset = (hours * 3600) + (minutes * 60)
-
-    # time.mktime returns localtime, but calendar.timegm returns UTC time
-    timestamp = calendar.timegm(base_time)
-    timestamp -= seconds_offset
-    # Add back in the fractional seconds
-    timestamp += fract_seconds
-    return (timestamp, seconds_offset)
-
-
-def parse_merge_property(line):
-    """Parse a bzr:merge property value.
-
-    :param line: Line to parse
-    :return: List of revisions merged
-    """
-    if ' ' in line:
-        mutter('invalid revision id %r in merged property, skipping' % line)
-        return []
-
-    return filter(lambda x: x != "", line.split("\t"))
-
-
-def parse_revid_property(line):
-    """Parse a (revnum, revid) tuple as set in revision id properties.
-    :param line: line to parse
-    :return: tuple with (bzr_revno, revid)
-    """
-    if '\n' in line:
-        raise errors.InvalidPropertyValue(SVN_PROP_BZR_REVISION_ID, 
-                "newline in revision id property line")
-    try:
-        (revno, revid) = line.split(' ', 1)
-    except ValueError:
-        raise errors.InvalidPropertyValue(SVN_PROP_BZR_REVISION_ID, 
-                "missing space")
-    if revid == "":
-        raise errors.InvalidPropertyValue(SVN_PROP_BZR_REVISION_ID,
-                "empty revision id")
-    return (int(revno), revid)
-
-
-def parse_revision_metadata(text, rev):
-    """Parse a revision info text (as set in bzr:revision-info).
-
-    :param text: text to parse
-    :param rev: Revision object to apply read parameters to
-    """
-    in_properties = False
-    for l in text.splitlines():
-        try:
-            key, value = l.split(": ", 2)
-        except ValueError:
-            raise errors.InvalidPropertyValue(SVN_PROP_BZR_REVISION_INFO, 
-                    "Missing : in revision metadata")
-        if key == "committer":
-            rev.committer = value.decode("utf-8")
-        elif key == "timestamp":
-            (rev.timestamp, rev.timezone) = unpack_highres_date(value)
-        elif key == "properties":
-            in_properties = True
-        elif key[0] == "\t" and in_properties:
-            rev.properties[str(key[1:])] = value.decode("utf-8")
-        else:
-            raise errors.InvalidPropertyValue(SVN_PROP_BZR_REVISION_INFO, 
-                    "Invalid key %r" % key)
-
-
-def generate_revision_metadata(timestamp, timezone, committer, revprops):
-    """Generate revision metadata text for the specified revision 
-    properties.
-
-    :param timestamp: timestamp of the revision, in seconds since epoch
-    :param timezone: timezone, specified by offset from GMT in seconds
-    :param committer: name/email of the committer
-    :param revprops: dictionary with custom revision properties
-    :return: text with data to set bzr:revision-info to.
-    """
-    assert timestamp is None or isinstance(timestamp, float)
-    text = ""
-    if timestamp is not None:
-        text += "timestamp: %s\n" % format_highres_date(timestamp, timezone) 
-    if committer is not None:
-        text += "committer: %s\n" % committer
-    if revprops is not None and revprops != {}:
-        text += "properties: \n"
-        for k, v in sorted(revprops.items()):
-            text += "\t%s: %s\n" % (k, v)
-    return text
-
 
 def parse_svk_feature(feature):
     """Parse a svk feature identifier.
@@ -263,6 +103,8 @@ class SvnRepositoryFormat(RepositoryFormat):
     def check_conversion_target(self, target_repo_format):
         return target_repo_format.rich_root_data
 
+CACHE_DB_VERSION = 3
+
 cachedbs = {}
 
 class SvnRepository(Repository):
@@ -293,10 +135,8 @@ class SvnRepository(Repository):
         self.get_config().add_location(self.base)
         cache_dir = self.create_cache_dir()
         cachedir_transport = get_transport(cache_dir)
-        cache_file = os.path.join(cache_dir, 'cache-v%d' % MAPPING_VERSION)
+        cache_file = os.path.join(cache_dir, 'cache-v%d' % CACHE_DB_VERSION)
         if not cachedbs.has_key(cache_file):
-            if not os.path.exists(cache_file):
-                info("Initialising Subversion metadata cache in %s" % cache_file)
             cachedbs[cache_file] = sqlite3.connect(cache_file)
         self.cachedb = cachedbs[cache_file]
 
@@ -411,6 +251,7 @@ class SvnRepository(Repository):
         cache_dir = create_cache_dir()
         dir = os.path.join(cache_dir, self.uuid)
         if not os.path.exists(dir):
+            info("Initialising Subversion metadata cache in %s" % dir)
             os.mkdir(dir)
         return dir