source: tailor/vcpx/dualwd.py @ 770

Revision 770, 4.1 KB checked in by lele@…, 8 years ago (diff)

Use --ignore-times with rsync, when we are going too fast

Line 
1# -*- mode: python; coding: utf-8 -*-
2# :Progetto: vcpx -- Dual working directory
3# :Creato:   dom 20 giu 2004 11:02:01 CEST
4# :Autore:   Lele Gaifax <lele@nautilus.homeip.net>
5# :Licenza:  GNU General Public License
6#
7
8"""
9The easiest way to propagate changes from one VC control system to one
10of an another kind is having a single directory containing a live
11working copy shared between the two VC systems.
12
13In a slightly more elaborated way, the source and the target system may
14use separate directories, that gets rsynced when needed.
15
16This module implements `DualWorkingDir`, which instances have a
17`source` and `target` properties offering the right capabilities to do
18the job.
19"""
20
21__docformat__ = 'reStructuredText'
22
23from source import UpdatableSourceWorkingDir, InvocationError
24from target import SyncronizableTargetWorkingDir
25from shwrap import ExternalCommand
26from datetime import datetime
27
28IGNORED_METADIRS = []
29
30class DualWorkingDir(UpdatableSourceWorkingDir, SyncronizableTargetWorkingDir):
31    """
32    Dual working directory, one that is under two different VC systems at
33    the same time.
34
35    This class reimplements the two interfaces, dispatching the right method
36    to the right backend.
37    """
38
39    def __init__(self, source_repo, target_repo):
40        global IGNORED_METADIRS
41
42        self.source = source_repo.workingDir()
43        self.target = target_repo.workingDir()
44
45        sbdir = self.source.basedir
46        tbdir = self.target.basedir
47        if sbdir == tbdir:
48            shared = True
49        elif tbdir.startswith(sbdir):
50            raise InvocationError('Target base directory %r cannot be a '
51                                  'subdirectory of source directory %r' %(
52                (tbdir, sbdir)))
53        elif sbdir.startswith(tbdir):
54            shared = True
55        else:
56            shared = False
57        self.shared_basedirs = shared
58        self.source.shared_basedirs = shared
59        self.target.shared_basedirs = shared
60
61        IGNORED_METADIRS = filter(None, [source_repo.METADIR,
62                                         target_repo.METADIR])
63        IGNORED_METADIRS.extend(source_repo.EXTRA_METADIRS)
64        IGNORED_METADIRS.extend(target_repo.EXTRA_METADIRS)
65
66        self.source.prepareSourceRepository()
67        self.target.prepareTargetRepository()
68
69        # UpdatableSourceWorkingDir
70
71        self.getPendingChangesets = self.source.getPendingChangesets
72        self.checkoutUpstreamRevision = self.source.checkoutUpstreamRevision
73
74        # SyncronizableTargetWorkingDir
75
76        self.prepareWorkingDirectory = self.target.prepareWorkingDirectory
77
78    def setStateFile(self, state_file):
79        """
80        Set the state file used to store the revision and pending changesets.
81        """
82
83        self.source.setStateFile(state_file)
84        self.target.setStateFile(state_file)
85
86    def setLogfile(self, logfile):
87        """
88        Set the name of the logfile, just to ignore it.
89        """
90
91        self.target.logfile = logfile
92
93    def applyPendingChangesets(self, applyable=None, replay=None, applied=None):
94        return self.source.applyPendingChangesets(replay=self.replayChangeset,
95                                                  applyable=applyable,
96                                                  applied=applied)
97
98    def importFirstRevision(self, source_repo, changeset, initial):
99        if not self.shared_basedirs:
100            self._syncTargetWithSource()
101        self.target.importFirstRevision(source_repo, changeset, initial)
102
103    def replayChangeset(self, changeset):
104        if not self.shared_basedirs:
105            self._syncTargetWithSource()
106        self.target.replayChangeset(changeset)
107
108    def _syncTargetWithSource(self):
109        cmd = ['rsync', '--delete', '--archive']
110        now = datetime.now()
111        if hasattr(self, '_last_rsync'):
112            last = self._last_rsync
113            if not (now-last).seconds:
114                cmd.append('--ignore-times')
115        self._last_rsync = now
116        for M in IGNORED_METADIRS:
117            cmd.extend(['--exclude', M])
118
119        rsync = ExternalCommand(command=cmd)
120        rsync.execute(self.source.basedir+'/', self.target.basedir)
Note: See TracBrowser for help on using the repository browser.