timestamp / timestamp.py

# timestamps.py - save or restore modification times of files
#
# Copyright 2009 Friedrich Kastner-Masilko <face@snoopie.at>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.

from mercurial.i18n import _
from mercurial import localrepo, util
import os, time

def hook(ui, repo, hooktype, parent1=None, parent2=None, **kwargs):
    '''hook for restoring timestamps after update'''    
    
    tsfile=''
    try:
        tsfile = file(repo.root+'/.hgtimestamp', 'r')        
    except:
        ui.debug('.hgtimestamp not found!\n')
        return

    tsdict= dict()
    tslist= list()

    ui.debug(_('Restoring timestamps\n'))
    for line in tsfile.readlines():
        try:
            fname, mtime = line.strip().split(',')
            tsdict[fname] = float(mtime)
            tslist.append(fname)
        except:            
            if len(line)>0:
                fname = line.strip().split(',')[0]
                tsdict[fname] = float(-1)
                tslist.append(fname)

    for f, mtime in tsdict.items():
        if mtime>=0:
            fname = repo.wjoin(f)
            try:
                st = os.stat(fname)
                os.utime(fname, (st.st_atime, type(st.st_mtime)(mtime)))
                ui.debug(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime(mtime)), " \t", f, "\n")
            except:
                ui.debug(_('File stat failed for "'), fname, '"!\n')                
        else:
            ui.debug(f, _(' skipped\n'))

def timestamp(ui, repo, **opts):
    '''save or restore modification times of files'''
    
    tsfile=''
    try:
        tsfile = file(repo.root+'/.hgtimestamp', 'r')        
    except:
        return True
    
    tsdict= dict()
    tslist= list()    
    for line in tsfile.readlines():
        try:
            fname, mtime = line.strip().split(',')
            tsdict[fname] = float(mtime)
            tslist.append(fname)
        except:
            if len(line)>0:
                fname = line.strip().split(',')[0]
                tsdict[fname] = float(-1)
                tslist.append(fname)

    if opts['save']:
        modified, added, removed, deleted, unknown, ignored, clean = [
            n for n in repo.status(clean=True)]
        patched = modified + added + clean
        changed = False
        ui.status(_('Checking timestamps\n'))
        for f in patched:
            if f in tsdict:
                fname = repo.wjoin(f)
                stamp = tsdict[f] = float(os.stat(fname).st_mtime)
                changed = True
                ui.status(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime(stamp)), " \t", f, "\n")
        if changed:
            pm = file(repo.root+'/.hgtimestamp', 'w')
            for fname in tslist:
                mtime=tsdict[fname]
                if mtime<0:
                    pm.write("%s\n" % fname)
                else:                    
                    pm.write("%s,%s\n" % (fname, tsdict[fname]))
        else:
            ui.status(_('No tracked timestamp\n'))
    elif opts['restore']:
        ui.status(_('Restoring timestamps\n'))
        for f, mtime in tsdict.items():
            if mtime>=0:
                fname = repo.wjoin(f)
                try:
                    st = os.stat(fname)
                    os.utime(fname, (st.st_atime, type(st.st_mtime)(mtime)))
                    ui.status(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime(mtime)), " \t", f, "\n")
                except:
                    ui.status(_('File stat failed for "'), fname, '"!\n')
            else:
                ui.status(f, _(' skipped\n'))
    else:        
        for fname in tslist:
            mtime=tsdict[fname]
            if mtime>=0:
                ui.status(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime(mtime)), " \t", fname, "\n")
            else:
                ui.debug(fname, _(' skipped\n'))
    return True

cmdtable = {
    "timestamp": 
        (timestamp, 
         [('s', 'save', None, _('save modification times')),
          ('r', 'restore', None, _('restore modification times'))], 
              _('hg timestamp [-s | -r]')),
}

def _commit(repo, text="", user=None, date=None, matchin=None,
                force=False, editor=False, extra={}):
    '''Hack to get a real precommit hook. One that allows to modify files e.g.
    The precommit hook is only called in localrepo.commit. I hope it is
    safe to only decorate localrepo.commit.
    Technique taken from Azra Aiyl's post here:
    http://www.nabble.com/sub-repository-extension-td20345412.html'''
    
    tsfile=''
    ignore=False
    try:
        tsfile = file(repo.root+'/.hgtimestamp', 'r')        
    except:
        ignore=True

    if ignore:
        pass
    else:
        tsdict= dict()
        tslist= list()
        repo.ui.debug(_('Checking timestamps\n'))
        for line in tsfile.readlines():
            try:
                fname, mtime = line.strip().split(',')
                tsdict[fname] = float(mtime)
                tslist.append(fname)
            except:
                if len(line)>0:
                    fname = line.strip().split(',')[0]
                    tsdict[fname] = float(-1)
                    tslist.append(fname)

        if matchin and len(matchin.files())>0:            
            match = matchin.files()
        else:
            modified, added, removed, deleted, unknown, ignored, clean = [
                n for n in repo.status()]
            match = modified + added

        changed = False
        for f in match:
            if f in tsdict and ((not matchin) or matchin(f)):
                fname = repo.wjoin(f)
                stamp = tsdict[f] = float(os.stat(fname).st_mtime)
                repo.ui.debug(time.strftime("%d.%m.%Y %H:%M:%S", time.localtime(stamp)), " \t", f, "\n")
                changed = True
        if changed:
            pm = file(repo.root+'/.hgtimestamp', 'w')
            for fname in tslist:
                mtime=tsdict[fname]
                if mtime<0:
                    pm.write("%s\n" % fname)
                else:                    
                    pm.write("%s,%s\n" % (fname, tsdict[fname]))
            if (not matchin) or matchin('.hgtimestamp'):
                pass
            else:
                def matchfn(fn):
                    if fn=='.hgtimestamp':
                        return True
                    else:
                        return matchin.timestamp_origmatchfn(fn)
                matchin.timestamp_origmatchfn=matchin.matchfn
                matchin.matchfn=matchfn
                if (len(matchin.files())>0):
                    matchin.files().append('.hgtimestamp')
            pm.close()
        else:
            repo.ui.debug(_('No tracked timestamp\n'))
                                            
    return repo.timestamp_origcommit(text, user, date, matchin, force, editor, extra)

localrepo.localrepository.timestamp_origcommit = localrepo.localrepository.commit
localrepo.localrepository.commit = _commit
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.