def TicksFromDateTime(datetime): """Return a unix timestamp from a MySQL DATETIME value""" if type(datetime) == types.StringType: # datetime is a MySQL DATETIME string matches = _re_datetime.match(datetime).groups() t = tuple(map(int, matches)) + (0, 0, 0) elif hasattr(datetime, "timetuple"): # datetime is a Python >=2.3 datetime.DateTime object t = datetime.timetuple() else: # datetime is an eGenix mx.DateTime object t = datetime.tuple() if utc_time: return compat.timegm(t) else: return time.mktime(t[:8] + (-1,))
def _parse_log_entry(fp): """Parse a single log entry. On entry, fp should point to the first line of the entry (the "revision" line). On exit, fp will have consumed the log separator line (dashes) or the end-of-file marker (equals). Returns: Revision object and eof flag (see _EOF_*) """ rev = None line = fp.readline() if not line: return None, _EOF_LOG if line == LOG_END_MARKER: # Needed because some versions of RCS precede LOG_END_MARKER # with ENTRY_END_MARKER return None, _EOF_FILE if line[:8] == 'revision': match = _re_rev.match(line) if not match: return None, _EOF_LOG rev = match.group(1) line = fp.readline() if not line: return None, _EOF_LOG match = _re_log_info.match(line) eof = None log = '' while 1: line = fp.readline() if not line: # true end-of-file eof = _EOF_LOG break if line[:9] == 'branches:': continue if line == ENTRY_END_MARKER: break if line == LOG_END_MARKER: # end of this file's log information eof = _EOF_FILE break log = log + line if not rev or not match: # there was a parsing error return None, eof # parse out a time tuple for the local time tm = compat.cvs_strptime(match.group(1)) # rlog seems to assume that two-digit years are 1900-based (so, "04" # comes out as "1904", not "2004"). EPOCH = 1970 if tm[0] < EPOCH: tm = list(tm) if (tm[0] - 1900) < 70: tm[0] = tm[0] + 100 if tm[0] < EPOCH: raise ValueError, 'invalid year' date = compat.timegm(tm) return Revision(rev, date, # author, state, lines changed match.group(2), match.group(3) == "dead", match.group(5), log), eof
def _parse_log_entry(fp): """Parse a single log entry. On entry, fp should point to the first line of the entry (the "revision" line). On exit, fp will have consumed the log separator line (dashes) or the end-of-file marker (equals). Returns: Revision object and eof flag (see _EOF_*) """ rev = None line = fp.readline() if not line: return None, _EOF_LOG if line == LOG_END_MARKER: # Needed because some versions of RCS precede LOG_END_MARKER # with ENTRY_END_MARKER return None, _EOF_FILE if line[:8] == 'revision': match = _re_rev.match(line) if not match: return None, _EOF_LOG rev = match.group(1) line = fp.readline() if not line: return None, _EOF_LOG match = _re_log_info.match(line) eof = None log = '' while 1: line = fp.readline() if not line: # true end-of-file eof = _EOF_LOG break if line[:9] == 'branches:': continue if line == ENTRY_END_MARKER: break if line == LOG_END_MARKER: # end of this file's log information eof = _EOF_FILE break log = log + line if not rev or not match: # there was a parsing error return None, eof # parse out a time tuple for the local time tm = compat.cvs_strptime(match.group(1)) # rlog seems to assume that two-digit years are 1900-based (so, "04" # comes out as "1904", not "2004"). EPOCH = 1970 if tm[0] < EPOCH: tm = list(tm) if (tm[0] - 1900) < 70: tm[0] = tm[0] + 100 if tm[0] < EPOCH: raise ValueError, 'invalid year' date = compat.timegm(tm) return Revision( rev, date, # author, state, lines changed match.group(2), match.group(3) == "dead", match.group(5), log), eof
def parse_rcs_tree(self): while 1: revision = self.ts.get() # End of RCS tree description ? if revision == 'desc': self.ts.unget(revision) return # Parse date semi, date, sym = self.ts.mget(3) if sym != 'date': raise RCSExpected(sym, 'date') if semi != ';': raise RCSExpected(semi, ';') # Convert date into timestamp date_fields = string.split(date, '.') + ['0', '0', '0'] date_fields = map(string.atoi, date_fields) # need to make the date four digits for timegm EPOCH = 1970 if date_fields[0] < EPOCH: if date_fields[0] < 70: date_fields[0] = date_fields[0] + 2000 else: date_fields[0] = date_fields[0] + 1900 if date_fields[0] < EPOCH: raise ValueError, 'invalid year' timestamp = compat.timegm(tuple(date_fields)) # Parse author ### NOTE: authors containing whitespace are violations of the ### RCS specification. We are making an allowance here because ### CVSNT is known to produce these sorts of authors. self.ts.match('author') author = '' while 1: token = self.ts.get() if token == ';': break author = author + token + ' ' author = author[:-1] # toss the trailing space # Parse state self.ts.match('state') state = '' while 1: token = self.ts.get() if token == ';': break state = state + token + ' ' state = state[:-1] # toss the trailing space # Parse branches self.ts.match('branches') branches = [ ] while 1: token = self.ts.get() if token == ';': break branches.append(token) # Parse revision of next delta in chain next, sym = self.ts.mget(2) if sym != 'next': raise RCSExpected(sym, 'next') if next == ';': next = None else: self.ts.match(';') # there are some files with extra tags in them. for example: # owner 640; # group 15; # permissions 644; # hardlinks @configure.in@; # this is "newphrase" in RCSFILE(5). we just want to skip over these. while 1: token = self.ts.get() if token == 'desc' or token[0] in string.digits: self.ts.unget(token) break # consume everything up to the semicolon while self.ts.get() != ';': pass self.sink.define_revision(revision, timestamp, author, state, branches, next)
def parse_rcs_tree(self): while 1: revision = self.ts.get() # End of RCS tree description ? if revision == 'desc': self.ts.unget(revision) return # Parse date semi, date, sym = self.ts.mget(3) if sym != 'date': raise RCSExpected(sym, 'date') if semi != ';': raise RCSExpected(semi, ';') # Convert date into timestamp date_fields = string.split(date, '.') + ['0', '0', '0'] date_fields = map(string.atoi, date_fields) # need to make the date four digits for timegm EPOCH = 1970 if date_fields[0] < EPOCH: if date_fields[0] < 70: date_fields[0] = date_fields[0] + 2000 else: date_fields[0] = date_fields[0] + 1900 if date_fields[0] < EPOCH: raise ValueError, 'invalid year' timestamp = compat.timegm(tuple(date_fields)) # Parse author ### NOTE: authors containing whitespace are violations of the ### RCS specification. We are making an allowance here because ### CVSNT is known to produce these sorts of authors. self.ts.match('author') author = '' while 1: token = self.ts.get() if token == ';': break author = author + token + ' ' author = author[:-1] # toss the trailing space # Parse state self.ts.match('state') state = '' while 1: token = self.ts.get() if token == ';': break state = state + token + ' ' state = state[:-1] # toss the trailing space # Parse branches self.ts.match('branches') branches = [] while 1: token = self.ts.get() if token == ';': break branches.append(token) # Parse revision of next delta in chain next, sym = self.ts.mget(2) if sym != 'next': raise RCSExpected(sym, 'next') if next == ';': next = None else: self.ts.match(';') # there are some files with extra tags in them. for example: # owner 640; # group 15; # permissions 644; # hardlinks @configure.in@; # this is "newphrase" in RCSFILE(5). we just want to skip over these. while 1: token = self.ts.get() if token == 'desc' or token[0] in string.digits: self.ts.unget(token) break # consume everything up to the semicolon while self.ts.get() != ';': pass self.sink.define_revision(revision, timestamp, author, state, branches, next)