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.
def check_conversion_target(self, target_repo_format):
return target_repo_format.rich_root_data
+CACHE_DB_VERSION = 3
+
cachedbs = {}
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]
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