Preserving timestamps

Henryk Gerlach hgerlach at gmx.de
Tue Aug 7 10:29:54 CDT 2007



> From: "Miguel Freitas" (miguel cpti cetuc puc-rio br)
> Subject: Preserving timestamps

> Before you fry me in boiling oil... :-)
> I did read the FAQ ("Why is the modification time of files not
> restored on checkout?") and recent messages on ml ("Maintaining
> modified dates of files"). but...
> 
> I'm currently using hg to manage a FPGA project with Xilinx tools.
> Their IDE stores about all files, schematics and stuff in plain text,
> which is a very good thing to allow using hg.
>
> My question is, i know preserving mtimes is bad in general, but is it
> possible to implement this feature for a specific set of files in a
> repository?
Okay, I gave it a shot, just for the fun of it.

Try the follwing two scripts (and share your improvements)

==== save-timestamps:begin ====
#!/usr/bin/env python
"""
Setup
=====

1. put save-timestamps and restore-timestamps in your path.

2. set up a timestamp container in the base of your repository

% touch .timestamps
% hg add .timestamps

3. set the hooks, i.e. add the lines to your .hg/hgrc

[hooks]
precommit= hg status | ~/bin/save-timestamps
update=~/bin/restore-timestamps

4. optionally register all files from your manifest

% (for f in $(hg manifest); do echo "A $f"; done) | save-timestamps


Bugs and Issues
===============
- There may be problems with timezones.
- The script should treat ".timestamps" more carefully (i.e. atomic save).
- ".timestamps" should possibly be in a human readable format
- Files that just change the timestamp but not content are not registered
- Filenames with strange characters like "\n" will cause problems
- Does this script scale?
- Can you replace it with a standard Unix-tool?
"""

import sys, os.path, time, pickle

VERSION = 0
timeStampDict = {}

def get_atime(path):
#  return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(os.path.getmtime(path)))  #this for touch -d
  return (os.path.getatime(path),os.path.getmtime(path),
          time.strftime("%Y-%m-%d %H:%M:%S %Z",time.localtime(os.path.getatime(path))),
          time.strftime("%Y-%m-%d %H:%M:%S %Z",time.localtime(os.path.getmtime(path))) )

def load_timeStampDict(filename=".timestamps"):
   global timeStampDict, VERSION
   try:
      f = open(filename,'rb')
      data = pickle.load(f)
      if data[0] > VERSION:
         print >>sys.stderr, "Don't know how to read VERSION=%s" % VERSION
         raise
      timeStampDict = data[1]
   except:
      print >>sys.stderr, "Could not open %s" % filename
      timeStampDict = {}


def save_timeStampDict(filename=".timestamps"):
   global timeStampDict, VERSION
   f = open(filename,'wb')
   pickle.dump((VERSION,timeStampDict),f)

def scan_hg_status():
   global timeStampDict
   for line in sys.stdin:
      state = line[0]
      filename = line[2:-1]
      if state in ["M","A"]:
         print "recording timestamp of %s" % filename
         timeStampDict[filename]=get_atime(filename)
      elif state in ["R"] and timeStampDict.has_key(filename):
         del timeStampDict[filename]
      elif state in ["?","!"]:
         pass
      else:
         print "Unkown state!"
         raise state

load_timeStampDict()
scan_hg_status()
save_timeStampDict()
==== save-timestamps:end ====


==== restore-timestamps:begin ====
#!/usr/bin/env python

import sys, os, time, pickle

VERSION = 0
timeStampDict = {}

def set_times(path,times):
   " times =(atime, mtime) "
   print "Restoring %s timestamp" % path
   os.utime(path,times)


def load_timeStampDict(filename=".timestamps"):
   global timeStampDict, VERSION
   try:
      f = open(filename,'rb')
      data = pickle.load(f)
      if data[0] > VERSION:
         raise "Don't know how to read VERSION=%s" % VERSION
      timeStampDict = data[1]
   except:
      print >>sys.stderr, "Could not open %s" % filename
      timeStampDict = {}


load_timeStampDict()
for filename in timeStampDict.keys():
   t=timeStampDict[filename]
   set_times(filename,(t[0],t[1]))
==== restore-timestamps:end ====


Have fun,
  Henryk
-- 
Psssst! Schon vom neuen GMX MultiMessenger gehört?
Der kanns mit allen: http://www.gmx.net/de/go/multimessenger


More information about the Mercurial mailing list