From 8b8faaf74ce154f9f2275bef92d514e4fe160d09 Mon Sep 17 00:00:00 2001
From: Michal Sojka
Date: Fri, 10 Oct 2008 14:34:14 +0200
Subject: [PATCH] Time renamed to RTime to avoid ambiguity on case insensitive filesystems
---
rdiff_backup/Hardlink.py | 2 +-
rdiff_backup/Main.py | 42 ++++----
rdiff_backup/RTime.py | 247 ++++++++++++++++++++++++++++++++++++++++++++
rdiff_backup/Security.py | 4 +-
rdiff_backup/Time.py | 247 --------------------------------------------
rdiff_backup/backup.py | 4 +-
rdiff_backup/connection.py | 2 +-
rdiff_backup/increment.py | 6 +-
rdiff_backup/manage.py | 12 +-
rdiff_backup/metadata.py | 6 +-
rdiff_backup/regress.py | 8 +-
rdiff_backup/restore.py | 2 +-
rdiff_backup/rpath.py | 6 +-
rdiff_backup/statistics.py | 14 ++--
14 files changed, 301 insertions(+), 301 deletions(-)
create mode 100644 rdiff_backup/RTime.py
delete mode 100644 rdiff_backup/Time.py
diff --git a/rdiff_backup/Hardlink.py b/rdiff_backup/Hardlink.py
index d0cb19f..53fa93e 100644
--- a/rdiff_backup/Hardlink.py
+++ b/rdiff_backup/Hardlink.py
@@ -31,7 +31,7 @@ source side should only transmit inode information.
"""
from __future__ import generators
-import Globals, Time, log, robust, errno
+import Globals, RTime, log, robust, errno
# The keys in this dictionary are (inode, devloc) pairs. The values
# are a pair (index, remaining_links, dest_key, sha1sum) where index
diff --git a/rdiff_backup/Main.py b/rdiff_backup/Main.py
index 6e050c0..06a6c80 100644
--- a/rdiff_backup/Main.py
+++ b/rdiff_backup/Main.py
@@ -22,7 +22,7 @@
from __future__ import generators
import getopt, sys, re, os, cStringIO, tempfile
from log import Log, LoggerError, ErrorLog
-import Globals, Time, SetConnections, selection, robust, rpath, \
+import Globals, RTime, SetConnections, selection, robust, rpath, \
manage, backup, connection, restore, FilenameMapping, \
Security, Hardlink, regress, C, fs_abilities, statistics, compare
@@ -244,7 +244,7 @@ def commandline_error(message):
def misc_setup(rps):
"""Set default change ownership flag, umask, relay regexps"""
os.umask(077)
- Time.setcurtime(Globals.current_time)
+ RTime.setcurtime(Globals.current_time)
SetConnections.UpdateGlobal("client_conn", Globals.local_connection)
Globals.postset_regexp('no_compression_regexp',
Globals.no_compression_regexp_string)
@@ -336,7 +336,7 @@ def Backup(rpin, rpout):
backup_set_select(rpin)
backup_warn_if_infinite_regress(rpin, rpout)
if prevtime:
- Time.setprevtime(prevtime)
+ RTime.setprevtime(prevtime)
rpout.conn.Main.backup_touch_curmirror_local(rpin, rpout)
backup.Mirror_and_increment(rpin, rpout, incdir)
rpout.conn.Main.backup_remove_curmirror_local()
@@ -434,10 +434,10 @@ def backup_final_init(rpout):
Log.open_logfile(Globals.rbdir.append("backup.log"))
checkdest_if_necessary(rpout)
prevtime = backup_get_mirrortime()
- if prevtime >= Time.curtime: Log.FatalError(
+ if prevtime >= RTime.curtime: Log.FatalError(
"""Time of Last backup is not in the past. This is probably caused
by running two backups in less than a second. Wait a second a try again.""")
- ErrorLog.open(Time.curtimestr, compress = Globals.compression)
+ ErrorLog.open(RTime.curtimestr, compress = Globals.compression)
if not incdir.lstat(): incdir.mkdir()
def backup_touch_curmirror_local(rpin, rpout):
@@ -452,7 +452,7 @@ def backup_touch_curmirror_local(rpin, rpout):
everything else is in place.
"""
- mirrorrp = Globals.rbdir.append("current_mirror.%s.%s" % (Time.curtimestr,
+ mirrorrp = Globals.rbdir.append("current_mirror.%s.%s" % (RTime.curtimestr,
"data"))
Log("Writing mirror marker %s" % mirrorrp.path, 6)
try: pid = os.getpid()
@@ -490,8 +490,8 @@ def Restore(src_rp, dest_rp, restore_as_of = None):
restore_check_backup_dir(restore_root, src_rp, restore_as_of)
inc_rpath = Globals.rbdir.append_path('increments', restore_index)
if restore_as_of:
- try: time = Time.genstrtotime(restore_timestr, rp = inc_rpath)
- except Time.TimeException, exc: Log.FatalError(str(exc))
+ try: time = RTime.genstrtotime(restore_timestr, rp = inc_rpath)
+ except RTime.TimeException, exc: Log.FatalError(str(exc))
else: time = src_rp.getinctime()
restore_set_select(restore_root, dest_rp)
restore_start_log(src_rp, dest_rp, time)
@@ -539,7 +539,7 @@ def restore_start_log(rpin, target, time):
# Log following message at file verbosity 3, but term verbosity 4
log_message = ("Starting restore of %s to %s as it was as of %s." %
- (rpin.path, target.path, Time.timetopretty(time)))
+ (rpin.path, target.path, RTime.timetopretty(time)))
if Log.term_verbosity >= 4: Log.log_to_term(log_message, 4)
if Log.verbosity >= 3: Log.log_to_file(log_message)
@@ -681,19 +681,19 @@ def RemoveOlderThan(rootrp):
def rot_check_time(time_string):
"""Check remove older than time_string, return time in seconds"""
- try: time = Time.genstrtotime(time_string)
- except Time.TimeException, exc: Log.FatalError(str(exc))
+ try: time = RTime.genstrtotime(time_string)
+ except RTime.TimeException, exc: Log.FatalError(str(exc))
times_in_secs = [inc.getinctime() for inc in
restore.get_inclist(Globals.rbdir.append_path("increments"))]
times_in_secs = filter(lambda t: t < time, times_in_secs)
if not times_in_secs:
Log("No increments older than %s found, exiting." %
- (Time.timetopretty(time),), 3)
+ (RTime.timetopretty(time),), 3)
return None
times_in_secs.sort()
- inc_pretty_time = "\n".join(map(Time.timetopretty, times_in_secs))
+ inc_pretty_time = "\n".join(map(RTime.timetopretty, times_in_secs))
if len(times_in_secs) > 1 and not force:
Log.FatalError("Found %d relevant increments, dated:\n%s"
"\nIf you want to delete multiple increments in this way, "
@@ -714,8 +714,8 @@ def rot_require_rbdir_base(rootrp):
def ListChangedSince(rp):
"""List all the files under rp that have changed since restoretime"""
rp = require_root_set(rp, 1)
- try: rest_time = Time.genstrtotime(restore_timestr)
- except Time.TimeException, exc: Log.FatalError(str(exc))
+ try: rest_time = RTime.genstrtotime(restore_timestr)
+ except RTime.TimeException, exc: Log.FatalError(str(exc))
mirror_rp = restore_root.new_index(restore_index)
inc_rp = mirror_rp.append_path("increments", restore_index)
for rorp in rp.conn.restore.ListChangedSince(mirror_rp, inc_rp, rest_time):
@@ -726,8 +726,8 @@ def ListChangedSince(rp):
def ListAtTime(rp):
"""List files in archive under rp that are present at restoretime"""
rp = require_root_set(rp, 1)
- try: rest_time = Time.genstrtotime(restore_timestr)
- except Time.TimeException, exc: Log.FatalError(str(exc))
+ try: rest_time = RTime.genstrtotime(restore_timestr)
+ except RTime.TimeException, exc: Log.FatalError(str(exc))
mirror_rp = restore_root.new_index(restore_index)
inc_rp = mirror_rp.append_path("increments", restore_index)
for rorp in rp.conn.restore.ListAtTime(mirror_rp, inc_rp, rest_time):
@@ -747,8 +747,8 @@ def Compare(compare_type, src_rp, dest_rp, compare_time = None):
global return_val
dest_rp = require_root_set(dest_rp, 1)
if not compare_time:
- try: compare_time = Time.genstrtotime(restore_timestr)
- except Time.TimeException, exc: Log.FatalError(str(exc))
+ try: compare_time = RTime.genstrtotime(restore_timestr)
+ except RTime.TimeException, exc: Log.FatalError(str(exc))
mirror_rp = restore_root.new_index(restore_index)
inc_rp = Globals.rbdir.append_path("increments", restore_index)
@@ -765,8 +765,8 @@ def Verify(dest_rp, verify_time = None):
global return_val
dest_rp = require_root_set(dest_rp, 1)
if not verify_time:
- try: verify_time = Time.genstrtotime(restore_timestr)
- except Time.TimeException, exc: Log.FatalError(str(exc))
+ try: verify_time = RTime.genstrtotime(restore_timestr)
+ except RTime.TimeException, exc: Log.FatalError(str(exc))
mirror_rp = restore_root.new_index(restore_index)
inc_rp = Globals.rbdir.append_path("increments", restore_index)
diff --git a/rdiff_backup/RTime.py b/rdiff_backup/RTime.py
new file mode 100644
index 0000000..6ee3b0a
--- /dev/null
+++ b/rdiff_backup/RTime.py
@@ -0,0 +1,247 @@
+# Copyright 2002 Ben Escoto
+#
+# This file is part of rdiff-backup.
+#
+# rdiff-backup is free software; you can redistribute it and/or modify
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# rdiff-backup is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with rdiff-backup; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+"""Provide time related exceptions and functions"""
+
+import time, types, re, sys, calendar
+import Globals
+
+
+class TimeException(Exception): pass
+
+_interval_conv_dict = {"s": 1, "m": 60, "h": 3600, "D": 86400,
+ "W": 7*86400, "M": 30*86400, "Y": 365*86400}
+_integer_regexp = re.compile("^[0-9]+$")
+_session_regexp = re.compile("^[0-9]+B$")
+_interval_regexp = re.compile("^([0-9]+)([smhDWMY])")
+_genstr_date_regexp1 = re.compile("^(?P[0-9]{4})[-/]"
+ "(?P[0-9]{1,2})[-/](?P[0-9]{1,2})$")
+_genstr_date_regexp2 = re.compile("^(?P[0-9]{1,2})[-/]"
+ "(?P[0-9]{1,2})[-/](?P[0-9]{4})$")
+curtime = curtimestr = None
+
+def setcurtime(curtime = None):
+ """Sets the current time in curtime and curtimestr on all systems"""
+ t = curtime or time.time()
+ for conn in Globals.connections:
+ conn.RTime.setcurtime_local(long(t))
+
+def setcurtime_local(timeinseconds):
+ """Only set the current time locally"""
+ global curtime, curtimestr
+ curtime, curtimestr = timeinseconds, timetostring(timeinseconds)
+
+def setprevtime(timeinseconds):
+ """Sets the previous inc time in prevtime and prevtimestr"""
+ assert 0 < timeinseconds < curtime, \
+ "Time %s is out of bounds" % (timeinseconds,)
+ timestr = timetostring(timeinseconds)
+ for conn in Globals.connections:
+ conn.RTime.setprevtime_local(timeinseconds, timestr)
+
+def setprevtime_local(timeinseconds, timestr):
+ """Like setprevtime but only set the local version"""
+ global prevtime, prevtimestr
+ prevtime, prevtimestr = timeinseconds, timestr
+
+def timetostring(timeinseconds):
+ """Return w3 datetime compliant listing of timeinseconds"""
+ s = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(timeinseconds))
+ return s + gettzd(timeinseconds)
+
+def stringtotime(timestring):
+ """Return time in seconds from w3 timestring
+
+ If there is an error parsing the string, or it doesn't look
+ like a w3 datetime string, return None.
+
+ """
+ try:
+ date, daytime = timestring[:19].split("T")
+ year, month, day = map(int, date.split("-"))
+ hour, minute, second = map(int, daytime.split(":"))
+ assert 1900 < year < 2100, year
+ assert 1 <= month <= 12
+ assert 1 <= day <= 31
+ assert 0 <= hour <= 23
+ assert 0 <= minute <= 59
+ assert 0 <= second <= 61 # leap seconds
+ timetuple = (year, month, day, hour, minute, second, -1, -1, 0)
+ utc_in_secs = calendar.timegm(timetuple)
+
+ return long(utc_in_secs) + tzdtoseconds(timestring[19:])
+ except (TypeError, ValueError, AssertionError): return None
+
+def timetopretty(timeinseconds):
+ """Return pretty version of time"""
+ return time.asctime(time.localtime(timeinseconds))
+
+def stringtopretty(timestring):
+ """Return pretty version of time given w3 time string"""
+ return timetopretty(stringtotime(timestring))
+
+def prettytotime(prettystring):
+ """Converts time like "Mon Jun 5 11:00:23" to epoch sec, or None"""
+ try: return time.mktime(time.strptime(prettystring))
+ except ValueError: return None
+
+def inttopretty(seconds):
+ """Convert num of seconds to readable string like "2 hours"."""
+ partlist = []
+ hours, seconds = divmod(seconds, 3600)
+ if hours > 1: partlist.append("%d hours" % hours)
+ elif hours == 1: partlist.append("1 hour")
+
+ minutes, seconds = divmod(seconds, 60)
+ if minutes > 1: partlist.append("%d minutes" % minutes)
+ elif minutes == 1: partlist.append("1 minute")
+
+ if seconds == 1: partlist.append("1 second")
+ elif not partlist or seconds > 1:
+ if isinstance(seconds, int) or isinstance(seconds, long):
+ partlist.append("%s seconds" % seconds)
+ else: partlist.append("%.2f seconds" % seconds)
+ return " ".join(partlist)
+
+def intstringtoseconds(interval_string):
+ """Convert a string expressing an interval (e.g. "4D2s") to seconds"""
+ def error():
+ raise TimeException("""Bad interval string "%s"
+
+Intervals are specified like 2Y (2 years) or 2h30m (2.5 hours). The
+allowed special characters are s, m, h, D, W, M, and Y. See the man
+page for more information.
+""" % interval_string)
+ if len(interval_string) < 2: error()
+
+ total = 0
+ while interval_string:
+ match = _interval_regexp.match(interval_string)
+ if not match: error()
+ num, ext = int(match.group(1)), match.group(2)
+ if not ext in _interval_conv_dict or num < 0: error()
+ total += num*_interval_conv_dict[ext]
+ interval_string = interval_string[match.end(0):]
+ return total
+
+def gettzd(timeinseconds = None):
+ """Return w3's timezone identification string.
+
+ Expresed as [+/-]hh:mm. For instance, PDT is -07:00 during
+ dayling savings and -08:00 otherwise. Zone is coincides with what
+ localtime(), etc., use. If no argument given, use the current
+ time.
+
+ """
+ if timeinseconds is None: timeinseconds = time.time()
+ dst_in_effect = time.daylight and time.localtime(timeinseconds)[8]
+ if dst_in_effect: offset = -time.altzone/60
+ else: offset = -time.timezone/60
+ if offset > 0: prefix = "+"
+ elif offset < 0: prefix = "-"
+ else: return "Z" # time is already in UTC
+
+ hours, minutes = map(abs, divmod(offset, 60))
+ assert 0 <= hours <= 23
+ assert 0 <= minutes <= 59
+ return "%s%02d:%02d" % (prefix, hours, minutes)
+
+def tzdtoseconds(tzd):
+ """Given w3 compliant TZD, return how far ahead UTC is"""
+ if tzd == "Z": return 0
+ assert len(tzd) == 6 # only accept forms like +08:00 for now
+ assert (tzd[0] == "-" or tzd[0] == "+") and tzd[3] == ":"
+ return -60 * (60 * int(tzd[:3]) + int(tzd[4:]))
+
+def cmp(time1, time2):
+ """Compare time1 and time2 and return -1, 0, or 1"""
+ if type(time1) is types.StringType:
+ time1 = stringtotime(time1)
+ assert time1 is not None
+ if type(time2) is types.StringType:
+ time2 = stringtotime(time2)
+ assert time2 is not None
+
+ if time1 < time2: return -1
+ elif time1 == time2: return 0
+ else: return 1
+
+def time_from_session(session_num, rp = None):
+ """Return time in seconds of given backup
+
+ The current mirror is session_num 0, the next oldest increment has
+ number 1, etc. Requires that the Globals.rbdir directory be set.
+
+ """
+ session_times = Globals.rbdir.conn.restore.MirrorStruct \
+ .get_increment_times()
+ session_times.sort()
+ if len(session_times) <= session_num:
+ return session_times[0] # Use oldest if too few backups
+ return session_times[-session_num-1]
+
+def genstrtotime(timestr, curtime = None, rp = None):
+ """Convert a generic time string to a time in seconds
+
+ rp is used when the time is of the form "4B" or similar. Then the
+ times of the increments of that particular file are used.
+
+ """
+ if curtime is None: curtime = globals()['curtime']
+ if timestr == "now": return curtime
+
+ def error():
+ raise TimeException("""Bad time string "%s"
+
+The acceptible time strings are intervals (like "3D64s"), w3-datetime
+strings, like "2002-04-26T04:22:01-07:00" (strings like
+"2002-04-26T04:22:01" are also acceptable - rdiff-backup will use the
+current time zone), or ordinary dates like 2/4/1997 or 2001-04-23
+(various combinations are acceptable, but the month always precedes
+the day).""" % timestr)
+
+ # Test for straight integer
+ if _integer_regexp.search(timestr): return int(timestr)
+
+ # Test for w3-datetime format, possibly missing tzd
+ t = stringtotime(timestr) or stringtotime(timestr+gettzd())
+ if t: return t
+
+ # Test for time given as number of backups, like 3B
+ if _session_regexp.search(timestr):
+ return time_from_session(int(timestr[:-1]), rp)
+
+ # Try for long time, like "Mon Jun 5 11:00:23 1990"
+ t = prettytotime(timestr)
+ if t is not None: return t
+
+ try: # test for an interval, like "2 days ago"
+ return curtime - intstringtoseconds(timestr)
+ except TimeException: pass
+
+ # Now check for dates like 2001/3/23
+ match = _genstr_date_regexp1.search(timestr) or \
+ _genstr_date_regexp2.search(timestr)
+ if not match: error()
+ timestr = "%s-%02d-%02dT00:00:00%s" % (match.group('year'),
+ int(match.group('month')), int(match.group('day')), gettzd())
+ t = stringtotime(timestr)
+ if t: return t
+ else: error()
+
diff --git a/rdiff_backup/Security.py b/rdiff_backup/Security.py
index 8dc26bc..c00dab3 100644
--- a/rdiff_backup/Security.py
+++ b/rdiff_backup/Security.py
@@ -138,7 +138,7 @@ def set_allowed_requests(sec_level):
sec_level == "all"):
l.extend(["rpath.make_file_dict", "os.listdir", "rpath.ea_get",
"rpath.acl_get", "rpath.setdata_local",
- "log.Log.log_to_file", "os.getuid", "Time.setcurtime_local",
+ "log.Log.log_to_file", "os.getuid", "RTime.setcurtime_local",
"rpath.gzip_open_local_read", "rpath.open_local_read",
"Hardlink.initialize_dictionaries", "user_group.uid2uname",
"user_group.gid2gname"])
@@ -190,7 +190,7 @@ def set_allowed_requests(sec_level):
if Globals.server:
l.extend(["SetConnections.init_connection_remote",
"log.Log.setverbosity", "log.Log.setterm_verbosity",
- "Time.setprevtime_local", "Globals.postset_regexp_local",
+ "RTime.setprevtime_local", "Globals.postset_regexp_local",
"Globals.set_select", "backup.SourceStruct.set_session_info",
"backup.DestinationStruct.set_session_info",
"user_group.init_user_mapping",
diff --git a/rdiff_backup/Time.py b/rdiff_backup/Time.py
deleted file mode 100644
index 377f0b7..0000000
--- a/rdiff_backup/Time.py
+++ /dev/null
@@ -1,247 +0,0 @@
-# Copyright 2002 Ben Escoto
-#
-# This file is part of rdiff-backup.
-#
-# rdiff-backup is free software; you can redistribute it and/or modify
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 2 of the License, or (at your
-# option) any later version.
-#
-# rdiff-backup is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with rdiff-backup; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA
-
-"""Provide time related exceptions and functions"""
-
-import time, types, re, sys, calendar
-import Globals
-
-
-class TimeException(Exception): pass
-
-_interval_conv_dict = {"s": 1, "m": 60, "h": 3600, "D": 86400,
- "W": 7*86400, "M": 30*86400, "Y": 365*86400}
-_integer_regexp = re.compile("^[0-9]+$")
-_session_regexp = re.compile("^[0-9]+B$")
-_interval_regexp = re.compile("^([0-9]+)([smhDWMY])")
-_genstr_date_regexp1 = re.compile("^(?P[0-9]{4})[-/]"
- "(?P[0-9]{1,2})[-/](?P[0-9]{1,2})$")
-_genstr_date_regexp2 = re.compile("^(?P[0-9]{1,2})[-/]"
- "(?P[0-9]{1,2})[-/](?P[0-9]{4})$")
-curtime = curtimestr = None
-
-def setcurtime(curtime = None):
- """Sets the current time in curtime and curtimestr on all systems"""
- t = curtime or time.time()
- for conn in Globals.connections:
- conn.Time.setcurtime_local(long(t))
-
-def setcurtime_local(timeinseconds):
- """Only set the current time locally"""
- global curtime, curtimestr
- curtime, curtimestr = timeinseconds, timetostring(timeinseconds)
-
-def setprevtime(timeinseconds):
- """Sets the previous inc time in prevtime and prevtimestr"""
- assert 0 < timeinseconds < curtime, \
- "Time %s is out of bounds" % (timeinseconds,)
- timestr = timetostring(timeinseconds)
- for conn in Globals.connections:
- conn.Time.setprevtime_local(timeinseconds, timestr)
-
-def setprevtime_local(timeinseconds, timestr):
- """Like setprevtime but only set the local version"""
- global prevtime, prevtimestr
- prevtime, prevtimestr = timeinseconds, timestr
-
-def timetostring(timeinseconds):
- """Return w3 datetime compliant listing of timeinseconds"""
- s = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(timeinseconds))
- return s + gettzd(timeinseconds)
-
-def stringtotime(timestring):
- """Return time in seconds from w3 timestring
-
- If there is an error parsing the string, or it doesn't look
- like a w3 datetime string, return None.
-
- """
- try:
- date, daytime = timestring[:19].split("T")
- year, month, day = map(int, date.split("-"))
- hour, minute, second = map(int, daytime.split(":"))
- assert 1900 < year < 2100, year
- assert 1 <= month <= 12
- assert 1 <= day <= 31
- assert 0 <= hour <= 23
- assert 0 <= minute <= 59
- assert 0 <= second <= 61 # leap seconds
- timetuple = (year, month, day, hour, minute, second, -1, -1, 0)
- utc_in_secs = calendar.timegm(timetuple)
-
- return long(utc_in_secs) + tzdtoseconds(timestring[19:])
- except (TypeError, ValueError, AssertionError): return None
-
-def timetopretty(timeinseconds):
- """Return pretty version of time"""
- return time.asctime(time.localtime(timeinseconds))
-
-def stringtopretty(timestring):
- """Return pretty version of time given w3 time string"""
- return timetopretty(stringtotime(timestring))
-
-def prettytotime(prettystring):
- """Converts time like "Mon Jun 5 11:00:23" to epoch sec, or None"""
- try: return time.mktime(time.strptime(prettystring))
- except ValueError: return None
-
-def inttopretty(seconds):
- """Convert num of seconds to readable string like "2 hours"."""
- partlist = []
- hours, seconds = divmod(seconds, 3600)
- if hours > 1: partlist.append("%d hours" % hours)
- elif hours == 1: partlist.append("1 hour")
-
- minutes, seconds = divmod(seconds, 60)
- if minutes > 1: partlist.append("%d minutes" % minutes)
- elif minutes == 1: partlist.append("1 minute")
-
- if seconds == 1: partlist.append("1 second")
- elif not partlist or seconds > 1:
- if isinstance(seconds, int) or isinstance(seconds, long):
- partlist.append("%s seconds" % seconds)
- else: partlist.append("%.2f seconds" % seconds)
- return " ".join(partlist)
-
-def intstringtoseconds(interval_string):
- """Convert a string expressing an interval (e.g. "4D2s") to seconds"""
- def error():
- raise TimeException("""Bad interval string "%s"
-
-Intervals are specified like 2Y (2 years) or 2h30m (2.5 hours). The
-allowed special characters are s, m, h, D, W, M, and Y. See the man
-page for more information.
-""" % interval_string)
- if len(interval_string) < 2: error()
-
- total = 0
- while interval_string:
- match = _interval_regexp.match(interval_string)
- if not match: error()
- num, ext = int(match.group(1)), match.group(2)
- if not ext in _interval_conv_dict or num < 0: error()
- total += num*_interval_conv_dict[ext]
- interval_string = interval_string[match.end(0):]
- return total
-
-def gettzd(timeinseconds = None):
- """Return w3's timezone identification string.
-
- Expresed as [+/-]hh:mm. For instance, PDT is -07:00 during
- dayling savings and -08:00 otherwise. Zone is coincides with what
- localtime(), etc., use. If no argument given, use the current
- time.
-
- """
- if timeinseconds is None: timeinseconds = time.time()
- dst_in_effect = time.daylight and time.localtime(timeinseconds)[8]
- if dst_in_effect: offset = -time.altzone/60
- else: offset = -time.timezone/60
- if offset > 0: prefix = "+"
- elif offset < 0: prefix = "-"
- else: return "Z" # time is already in UTC
-
- hours, minutes = map(abs, divmod(offset, 60))
- assert 0 <= hours <= 23
- assert 0 <= minutes <= 59
- return "%s%02d:%02d" % (prefix, hours, minutes)
-
-def tzdtoseconds(tzd):
- """Given w3 compliant TZD, return how far ahead UTC is"""
- if tzd == "Z": return 0
- assert len(tzd) == 6 # only accept forms like +08:00 for now
- assert (tzd[0] == "-" or tzd[0] == "+") and tzd[3] == ":"
- return -60 * (60 * int(tzd[:3]) + int(tzd[4:]))
-
-def cmp(time1, time2):
- """Compare time1 and time2 and return -1, 0, or 1"""
- if type(time1) is types.StringType:
- time1 = stringtotime(time1)
- assert time1 is not None
- if type(time2) is types.StringType:
- time2 = stringtotime(time2)
- assert time2 is not None
-
- if time1 < time2: return -1
- elif time1 == time2: return 0
- else: return 1
-
-def time_from_session(session_num, rp = None):
- """Return time in seconds of given backup
-
- The current mirror is session_num 0, the next oldest increment has
- number 1, etc. Requires that the Globals.rbdir directory be set.
-
- """
- session_times = Globals.rbdir.conn.restore.MirrorStruct \
- .get_increment_times()
- session_times.sort()
- if len(session_times) <= session_num:
- return session_times[0] # Use oldest if too few backups
- return session_times[-session_num-1]
-
-def genstrtotime(timestr, curtime = None, rp = None):
- """Convert a generic time string to a time in seconds
-
- rp is used when the time is of the form "4B" or similar. Then the
- times of the increments of that particular file are used.
-
- """
- if curtime is None: curtime = globals()['curtime']
- if timestr == "now": return curtime
-
- def error():
- raise TimeException("""Bad time string "%s"
-
-The acceptible time strings are intervals (like "3D64s"), w3-datetime
-strings, like "2002-04-26T04:22:01-07:00" (strings like
-"2002-04-26T04:22:01" are also acceptable - rdiff-backup will use the
-current time zone), or ordinary dates like 2/4/1997 or 2001-04-23
-(various combinations are acceptable, but the month always precedes
-the day).""" % timestr)
-
- # Test for straight integer
- if _integer_regexp.search(timestr): return int(timestr)
-
- # Test for w3-datetime format, possibly missing tzd
- t = stringtotime(timestr) or stringtotime(timestr+gettzd())
- if t: return t
-
- # Test for time given as number of backups, like 3B
- if _session_regexp.search(timestr):
- return time_from_session(int(timestr[:-1]), rp)
-
- # Try for long time, like "Mon Jun 5 11:00:23 1990"
- t = prettytotime(timestr)
- if t is not None: return t
-
- try: # test for an interval, like "2 days ago"
- return curtime - intstringtoseconds(timestr)
- except TimeException: pass
-
- # Now check for dates like 2001/3/23
- match = _genstr_date_regexp1.search(timestr) or \
- _genstr_date_regexp2.search(timestr)
- if not match: error()
- timestr = "%s-%02d-%02dT00:00:00%s" % (match.group('year'),
- int(match.group('month')), int(match.group('day')), gettzd())
- t = stringtotime(timestr)
- if t: return t
- else: error()
-
diff --git a/rdiff_backup/backup.py b/rdiff_backup/backup.py
index cf9c52d..a9ab611 100644
--- a/rdiff_backup/backup.py
+++ b/rdiff_backup/backup.py
@@ -22,7 +22,7 @@
from __future__ import generators
import errno
import Globals, metadata, rorpiter, RTempFile, Hardlink, robust, increment, \
- rpath, static, log, selection, Time, Rdiff, statistics, iterfile, \
+ rpath, static, log, selection, RTime, Rdiff, statistics, iterfile, \
hash, longname
def Mirror(src_rpath, dest_rpath):
@@ -137,7 +137,7 @@ class DestinationStruct:
metadata.SetManager()
if use_metadata:
- rorp_iter = metadata.ManagerObj.GetAtTime(Time.prevtime)
+ rorp_iter = metadata.ManagerObj.GetAtTime(RTime.prevtime)
if rorp_iter: return rorp_iter
return get_iter_from_fs()
diff --git a/rdiff_backup/connection.py b/rdiff_backup/connection.py
index 873d475..299a5ee 100644
--- a/rdiff_backup/connection.py
+++ b/rdiff_backup/connection.py
@@ -534,7 +534,7 @@ class VirtualFile:
# everything has to be available here for remote connection's use, but
# put at bottom to reduce circularities.
-import Globals, Time, Rdiff, Hardlink, FilenameMapping, C, Security, \
+import Globals, RTime, Rdiff, Hardlink, FilenameMapping, C, Security, \
Main, rorpiter, selection, increment, statistics, manage, lazy, \
iterfile, rpath, robust, restore, manage, backup, connection, \
RTempFile, SetConnections, librsync, log, regress, fs_abilities, \
diff --git a/rdiff_backup/increment.py b/rdiff_backup/increment.py
index afab0d2..1c41410 100644
--- a/rdiff_backup/increment.py
+++ b/rdiff_backup/increment.py
@@ -19,7 +19,7 @@
"""Provides functions and *ITR classes, for writing increment files"""
-import Globals, Time, rpath, Rdiff, log, statistics, robust
+import Globals, RTime, rpath, Rdiff, log, statistics, robust
def Increment(new, mirror, incpref):
@@ -112,8 +112,8 @@ def get_inc(rp, typestr, time = None):
whole filename is in the base (which is not quoted).
"""
- if time is None: time = Time.prevtime
- addtostr = lambda s: "%s.%s.%s" % (s, Time.timetostring(time), typestr)
+ if time is None: time = RTime.prevtime
+ addtostr = lambda s: "%s.%s.%s" % (s, RTime.timetostring(time), typestr)
if rp.index:
incrp = rp.__class__(rp.conn, rp.base, rp.index[:-1] +
(addtostr(rp.index[-1]),))
diff --git a/rdiff_backup/manage.py b/rdiff_backup/manage.py
index 2c9c7de..05c8ff7 100644
--- a/rdiff_backup/manage.py
+++ b/rdiff_backup/manage.py
@@ -21,7 +21,7 @@
from __future__ import generators
from log import Log
-import Globals, Time, static, statistics, restore, selection, FilenameMapping
+import Globals, RTime, static, statistics, restore, selection, FilenameMapping
class ManageException(Exception): pass
@@ -72,12 +72,12 @@ def describe_incs_human(incs, mirror_time, mirrorrp):
for time, inc in incpairs:
result.append(" %s %s" %
(FilenameMapping.unquote(inc.dirsplit()[1]),
- Time.timetopretty(time)))
+ RTime.timetopretty(time)))
else:
for time, inc in incpairs:
result.append(" %s %s" %
- (inc.dirsplit()[1], Time.timetopretty(time)))
- result.append("Current mirror: %s" % Time.timetopretty(mirror_time))
+ (inc.dirsplit()[1], RTime.timetopretty(time)))
+ result.append("Current mirror: %s" % RTime.timetopretty(mirror_time))
return "\n".join(result)
def delete_earlier_than(baserp, time):
@@ -127,7 +127,7 @@ class IncObj:
def pretty_time(self):
"""Return a formatted version of inc's time"""
- return Time.timetopretty(self.time)
+ return RTime.timetopretty(self.time)
def full_description(self):
"""Return string describing increment"""
@@ -193,7 +193,7 @@ def ListIncrementSizes(mirror_root, index):
"""Convert triple to display string"""
time, size, cum_size = triple
return "%24s %13s %15s" % \
- (Time.timetopretty(time),
+ (RTime.timetopretty(time),
stat_obj.get_byte_summary_string(size),
stat_obj.get_byte_summary_string(cum_size))
diff --git a/rdiff_backup/metadata.py b/rdiff_backup/metadata.py
index 1bbc5c6..6e0d433 100644
--- a/rdiff_backup/metadata.py
+++ b/rdiff_backup/metadata.py
@@ -56,7 +56,7 @@ field names and values.
from __future__ import generators
import re, gzip, os, binascii
-import log, Globals, rpath, Time, robust, increment, static, rorpiter
+import log, Globals, rpath, RTime, robust, increment, static, rorpiter
class ParsingError(Exception):
"""This is raised when bad or unparsable data is received"""
@@ -543,8 +543,8 @@ class Manager:
def _writer_helper(self, prefix, flatfileclass, typestr, time):
"""Used in the get_xx_writer functions, returns a writer class"""
- if time is None: timestr = Time.curtimestr
- else: timestr = Time.timetostring(time)
+ if time is None: timestr = RTime.curtimestr
+ else: timestr = RTime.timetostring(time)
filename = '%s.%s.%s' % (prefix, timestr, typestr)
rp = Globals.rbdir.append(filename)
assert not rp.lstat(), "File %s already exists!" % (rp.path,)
diff --git a/rdiff_backup/regress.py b/rdiff_backup/regress.py
index 51bfafc..335c5ac 100644
--- a/rdiff_backup/regress.py
+++ b/rdiff_backup/regress.py
@@ -36,7 +36,7 @@ be recovered.
from __future__ import generators
import signal, errno, re, os
import Globals, restore, log, rorpiter, RTempFile, metadata, rpath, C, \
- Time, backup, robust, longname
+ RTime, backup, robust, longname
# regress_time should be set to the time we want to regress back to
# (usually the time of the last successful backup)
@@ -89,7 +89,7 @@ def set_regress_time():
mirror_rp_to_delete = curmir_incs[0]
regress_time = curmir_incs[1].getinctime()
unsuccessful_backup_time = mirror_rp_to_delete.getinctime()
- log.Log("Regressing to " + Time.timetopretty(regress_time), 4)
+ log.Log("Regressing to " + RTime.timetopretty(regress_time), 4)
return manager, mirror_rp_to_delete
def set_restore_times():
@@ -149,7 +149,7 @@ def recreate_meta(meta_manager):
writer.close()
finalrp = Globals.rbdir.append("mirror_metadata.%s.snapshot.gz" %
- Time.timetostring(regress_time))
+ RTime.timetostring(regress_time))
assert not finalrp.lstat(), finalrp
rpath.rename(temprp[0], finalrp)
if Globals.fsync_directories: Globals.rbdir.fsync()
@@ -182,7 +182,7 @@ def yield_metadata():
metadata_iter = metadata.ManagerObj.GetAtTime(regress_time)
if metadata_iter: return metadata_iter
log.Log.FatalError("No metadata for time %s (%s) found,\ncannot regress"
- % (Time.timetopretty(regress_time), regress_time))
+ % (RTime.timetopretty(regress_time), regress_time))
def iterate_meta_rfs(mirror_rp, inc_rp):
"""Yield RegressFile objects with extra metadata information added
diff --git a/rdiff_backup/restore.py b/rdiff_backup/restore.py
index 1e2c4be..4b056b0 100644
--- a/rdiff_backup/restore.py
+++ b/rdiff_backup/restore.py
@@ -738,6 +738,6 @@ class PermissionChanger:
for index, rp, perms in self.open_index_list: rp.chmod(perms)
-import Globals, Time, Rdiff, Hardlink, selection, rpath, \
+import Globals, RTime, Rdiff, Hardlink, selection, rpath, \
log, robust, metadata, statistics, RTempFile, hash, longname
diff --git a/rdiff_backup/rpath.py b/rdiff_backup/rpath.py
index 0dadd43..0f990a5 100644
--- a/rdiff_backup/rpath.py
+++ b/rdiff_backup/rpath.py
@@ -36,7 +36,7 @@ are dealing with are local or remote.
"""
import os, stat, re, sys, shutil, gzip, socket, time, errno
-import Globals, Time, static, log, user_group, C
+import Globals, RTime, static, log, user_group, C
class SkipFileException(Exception):
@@ -364,7 +364,7 @@ def get_incfile_info(basename):
compressed = None
if len(dotsplit) < 3: return None
timestring, ext = dotsplit[-2:]
- if Time.stringtotime(timestring) is None: return None
+ if RTime.stringtotime(timestring) is None: return None
if not (ext == "snapshot" or ext == "dir" or
ext == "missing" or ext == "diff" or ext == "data"):
return None
@@ -1184,7 +1184,7 @@ class RPath(RORPath):
def getinctime(self):
"""Return time in seconds of an increment file"""
- return Time.stringtotime(self.inc_timestr)
+ return RTime.stringtotime(self.inc_timestr)
def getincbase(self):
"""Return the base filename of an increment file in rp form"""
diff --git a/rdiff_backup/statistics.py b/rdiff_backup/statistics.py
index b16fb12..f709ec8 100644
--- a/rdiff_backup/statistics.py
+++ b/rdiff_backup/statistics.py
@@ -20,7 +20,7 @@
"""Generate and process aggregated backup information"""
import re, os, time
-import Globals, Time, increment, log, static, metadata
+import Globals, RTime, increment, log, static, metadata
class StatsException(Exception): pass
@@ -136,16 +136,16 @@ class StatsObj:
timelist = []
if self.StartTime is not None:
timelist.append("StartTime %.2f (%s)\n" %
- (self.StartTime, Time.timetopretty(self.StartTime)))
+ (self.StartTime, RTime.timetopretty(self.StartTime)))
if self.EndTime is not None:
timelist.append("EndTime %.2f (%s)\n" %
- (self.EndTime, Time.timetopretty(self.EndTime)))
+ (self.EndTime, RTime.timetopretty(self.EndTime)))
if self.ElapsedTime or (self.StartTime is not None and
self.EndTime is not None):
if self.ElapsedTime is None:
self.ElapsedTime = self.EndTime - self.StartTime
timelist.append("ElapsedTime %.2f (%s)\n" %
- (self.ElapsedTime, Time.inttopretty(self.ElapsedTime)))
+ (self.ElapsedTime, RTime.inttopretty(self.ElapsedTime)))
return "".join(timelist)
def get_filestats_string(self):
@@ -270,7 +270,7 @@ class StatFileObj(StatsObj):
"""StatFileObj initializer - zero out file attributes"""
StatsObj.__init__(self)
for attr in self.stat_file_attrs: self.set_stat(attr, 0)
- if start_time is None: start_time = Time.curtime
+ if start_time is None: start_time = RTime.curtime
self.StartTime = start_time
self.Errors = 0
@@ -338,7 +338,7 @@ def write_active_statfileobj():
global _active_statfileobj
assert _active_statfileobj
rp_base = Globals.rbdir.append("session_statistics")
- session_stats_rp = increment.get_inc(rp_base, 'data', Time.curtime)
+ session_stats_rp = increment.get_inc(rp_base, 'data', RTime.curtime)
_active_statfileobj.finish()
_active_statfileobj.write_stats_to_rp(session_stats_rp)
_active_statfileobj = None
@@ -362,7 +362,7 @@ class FileStats:
assert not (cls._fileobj or cls._rp), (cls._fileobj, cls._rp)
rpbase = Globals.rbdir.append("file_statistics")
suffix = Globals.compression and 'data.gz' or 'data'
- cls._rp = increment.get_inc(rpbase, suffix, Time.curtime)
+ cls._rp = increment.get_inc(rpbase, suffix, RTime.curtime)
assert not cls._rp.lstat()
cls._fileobj = cls._rp.open("wb", compress = Globals.compression)
--
1.5.6.3