source: tailor/vcpx/tailor.py @ 43

Revision 43, 7.1 KB checked in by lele@…, 9 years ago (diff)

Reworked tailor.py frontend using vcpx

Line 
1#! /usr/bin/python
2# -*- mode: python; coding: utf-8 -*-
3# :Progetto: vcpx --
4# :Creato:   dom 04 lug 2004 00:40:54 CEST
5# :Autore:   Lele Gaifax <lele@nautilus.homeip.net>
6#
7
8"""
9"""
10
11__docformat__ = 'reStructuredText'
12
13from dualwd import DualWorkingDir
14
15STATUS_FILENAME = 'tailor.info'
16LOG_FILENAME = 'tailor.log'
17   
18class TailorizedProject(object):
19
20    def __init__(self, root):
21        import logging
22        from os import makedirs
23        from os.path import join, exists
24
25        self.root = root
26        if not exists(root):
27            makedirs(root)
28       
29        self.logger = logging.getLogger('tailor')
30        hdlr = logging.FileHandler(join(root, LOG_FILENAME))
31        formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')
32        hdlr.setFormatter(formatter)
33        self.logger.addHandler(hdlr) 
34        self.logger.setLevel(logging.INFO)
35
36        self.source_kind = self.target_kind = None
37               
38    def __saveStatus(self):
39        from os.path import join, exists
40
41        statusfilename = join(self.root, STATUS_FILENAME)
42        f = open(statusfilename, 'w')
43        print >>f, self.source_kind
44        print >>f, self.target_kind       
45        print >>f, self.module       
46        print >>f, self.upstream_repos
47        print >>f, self.upstream_revision
48        f.close()
49       
50    def __loadStatus(self):
51        from os.path import join, exists
52
53        statusfilename = join(self.root, STATUS_FILENAME)
54        f = open(statusfilename)
55        (srck, dstk,
56         module, upstream_repos, upstream_revision) = f.readlines()
57        self.source_kind = srck[:-1]
58        self.target_kind = dstk[:-1]
59        self.module = module[:-1]
60        self.upstream_repos = upstream_repos[:-1]
61        self.upstream_revision = upstream_revision[:-1]
62        f.close()
63
64    def bootstrap(self, source_kind, target_kind,
65                  repository, module, revision):
66        """
67        Bootstrap a new tailorized module.
68
69        Extract a copy of the `repository` at given `revision` in the `root`
70        directory and initialize a target repository with its content.
71        """
72
73        from os.path import join
74       
75        self.logger.info("Bootstrapping '%s'" % (self.root,))
76
77        dwd = DualWorkingDir(source_kind, target_kind)
78        self.logger.info("getting %s revision '%s' of '%s' from '%s'" % (
79            source_kind, revision, module, repository))
80        actual = dwd.checkoutUpstreamRevision(self.root, repository,
81                                              module, revision)
82        self.logger.info("initializing %s shadow" % target_kind)
83        dwd.initializeNewWorkingDir(self.root, repository, actual)
84
85        self.source_kind = source_kind
86        self.target_kind = target_kind
87        self.upstream_repos = repository
88        self.module = module       
89        self.upstream_revision = actual
90
91        self.__saveStatus()
92
93        self.logger.info("Bootstrap completed")
94
95    def update(self):
96        from os.path import join
97       
98        self.__loadStatus()
99
100        proj = join(self.root, self.module)
101        self.logger.info("Updating '%s' from revision '%s'" % (
102            proj, self.upstream_revision))
103       
104        dwd = DualWorkingDir(self.source_kind, self.target_kind)
105        actual,conflics = dwd.applyUpstreamChangesets(proj,
106                                                      self.upstream_revision)
107        if actual:
108            self.upstream_revision = actual.revision
109            self.__saveStatus()
110            self.logger.info("Update completed, now at revision '%s'" % (
111                self.upstream_revision,))
112        else:
113            self.logger.info("Update completed with no upstream changes")
114
115
116from optparse import OptionParser, OptionError, OptionGroup, make_option
117
118OPTIONS = [
119    make_option("-D", "--debug", dest="debug",
120                action="store_true", default=False),
121    make_option("-s", "--source-kind", dest="source_kind", metavar="VC-KIND",
122                help="Select the backend for the upstream source "
123                     "version control VC-KIND. Default is 'cvs'.",
124                default="cvs"),
125    make_option("-t", "--target-kind", dest="target_kind", metavar="VC-KIND",
126                help="Select VC-KIND as backend for the shadow repository, "
127                     "with 'darcs' as default.",
128                default="darcs"),   
129]   
130
131ACTIONS = [
132    make_option("-b", "--bootstrap", action="store_true", default=False,
133                help="Bootstrap mode, that is the initial copy of the "
134                     "upstream tree, given as an URI possibly followed "
135                     "by a revision."),
136    make_option("-i", "--info", action="store_true", default=False,
137                help="Just show ancestry information."),
138]
139
140class ExistingProjectError(Exception):
141    """
142    Raised when, in bootstrap mode, the directory for the project is already
143    there.
144    """
145
146class UnknownProjectError(Exception):
147    """
148    Raised when, in normal mode, the directory for the project does not
149    exist.
150    """
151
152class ProjectNotTailored(Exception):
153    """
154    Raised when trying to do something on a project that has not been
155    tailored.
156    """
157   
158def main():
159    """
160    Script entry point.
161
162    Parse the command line options and arguments, and for each
163    specified working copy directory (the current working directory by
164    default) execute the tailorization steps.
165    """
166   
167    from os import getcwd, chdir
168    from os.path import abspath, exists, join, split
169    from shwrap import SystemCommand
170   
171    parser = OptionParser(usage='%prog [options] [proj [URI[@revision]]]...',
172                          option_list=OPTIONS)
173    actions = OptionGroup(parser, "Other actions")
174    actions.add_options(ACTIONS)
175    parser.add_option_group(actions)
176   
177    options, args = parser.parse_args()
178   
179    SystemCommand.VERBOSE = options.debug
180   
181    base = getcwd()
182   
183    if len(args) == 0:
184        args.append(base)
185       
186    while args:
187        chdir(base)
188       
189        proj = args.pop(0)
190        root = abspath(proj)       
191        basedir, module = split(root)
192       
193        if options.bootstrap:
194            if exists(join(basedir, STATUS_FILENAME)):
195                raise ExistingProjectError(
196                    "Project %r cannot be bootstrapped twice" % proj)
197           
198            if not args:
199                raise OptionError('expected the source URI for %r' % proj,
200                                  '--bootstrap')
201            uri = args.pop(0)
202        else:               
203            uri = None
204           
205        if not options.bootstrap and not exists(proj):
206            raise UnknownProjectError("Project %r does not exist" % proj)
207           
208        tailored = TailorizedProject(basedir)
209       
210        if options.bootstrap:
211            if uri and '@' in uri:
212                uri, rev = uri.split('@')
213            else:
214                rev = 'HEAD'
215            tailored.bootstrap(options.source_kind, options.target_kind,
216                               uri, module, rev)
217        elif options.info:
218            pass
219        else:
220            tailored.update()
221            print
Note: See TracBrowser for help on using the repository browser.