source: CMT/HEAD/mgr/cmt_svn_checkout.py @ 498

Last change on this file since 498 was 498, checked in by rybkin, 15 years ago

See C.L. 393

  • Property svn:executable set to *
File size: 12.8 KB
Line 
1#!/usr/bin/env python
2
3"""cmt_svn_checkout.py: Checkout CMT package(s) from Subversion repository.
4
5Usage: cmt_svn_checkout.py [OPTION]... PATH...
6Checkout PATH(s) relative to or being Subversion repository URL(s).
7
8Mandatory arguments to long options are mandatory for short options too.
9  -r, --version-tag=REV        checkout version tag REV of PATH
10      --version-dir=DIR        use DIR as version directory instead of version tag
11  -d, --directory=DIR          checkout into DIR instead of (basename of) PATH
12  -o, --offset=OFFSET          checkout PATH at OFFSET relative to repository URL
13      --no_config              disable config step upon checkout
14      --without_version_directory do not create version directory upon PATH checkout
15      --with_version_directory create version directory upon PATH checkout (default)
16      --url=URL                checkout PATH from repository URL
17  -h, --help                   display this help and exit
18      --version                output version information and exit
19
20The SVNROOT, SVNTRUNK, SVNTAGS, and SVNBRANCHES environment variables specify repository URL of PATH, location of PATH trunk, tags, and branches (relatively to PATH) respectively.
21
22Report bugs to <CMT-L@IN2P3.FR>.
23"""
24
25__version__ = '0.1.4'
26__date__ = 'Mon Apr 29 2009'
27__author__ = 'Grigory Rybkin'
28
29import sys
30import getopt
31import os
32import posixpath
33import os.path
34import urlparse
35
36self = 'cmt_svn_checkout.py'
37try:
38    from svn import client, core
39except ImportError, e:
40    print >>sys.stderr, '%s: %s: cannot import Subversion Python bindings' \
41          % (self, str(e))
42    sys.exit(1)
43
44class ClientContext(object):
45    def __init__(self):
46        core.svn_config_ensure(None)
47        self.ctx = client.create_context()
48        self.providers = [
49            client.get_simple_provider(),
50            client.get_username_provider(),
51            client.get_ssl_server_trust_file_provider(),
52            client.get_ssl_client_cert_file_provider(),
53            client.get_ssl_client_cert_pw_file_provider()
54            ]
55        self.ctx.auth_baton = core.svn_auth_open(self.providers)
56        self.ctx.config = core.svn_config_get_config(None)
57
58    def __call__(self):
59        return self.ctx
60
61def cwd():
62    _gcwd = os.getcwd()
63    try:
64        _cwd = os.environ['PWD']
65        if _cwd and os.path.samefile(_cwd, _gcwd):
66            return _cwd
67        else:
68            return _gcwd
69    except (KeyError, AttributeError):
70        return _gcwd
71
72def cd(path):
73    new = os.path.normpath(os.path.join(cwd(), path))
74    os.chdir(path)
75    _gcwd = os.getcwd()
76    try:
77        if os.path.samefile(new, _gcwd):
78            os.environ['PWD'] = new
79        else:
80            os.environ['PWD'] = _gcwd
81    except AttributeError:
82        pass
83
84class CmtContext(object):
85    def __init__(self,
86                 config = True,
87                 with_version_directory = True,
88                 cleanup = False):
89        self.config = config
90        self.with_version_directory = with_version_directory
91        self.cleanup = cleanup
92
93    def write(self, p, version):
94        #print >> sys.stderr, 'write:', p, version
95        try:
96            t = version + '\n'
97            if os.path.exists(p):
98                f = open(p, 'r+')
99                b = f.tell()
100                v = f.read()
101                if v != t:
102                    f.seek(b)
103                    f.write(t)
104                    f.truncate()
105            else:
106                f = open(p, 'w')
107                f.write(t)
108            f.close()
109        except IOError, e:
110            print >> sys.stderr, e
111            return 1
112        return 0
113       
114    def generate(self, p):
115        #print >> sys.stderr, 'generate:', p
116        curdir = cwd()
117        cmd = 'cmt -disable_warnings'
118        if self.with_version_directory:
119            cmd += ' -with_version_directory'
120        else:
121            cmd += ' -without_version_directory'
122        if self.cleanup:
123            cmd += ' -cleanup'
124        else:
125            cmd += ' -no_cleanup'
126        cmd += ' config'
127        cd(p)
128        sc = os.system(cmd)
129        if sc != 0: sc = 1
130        cd(curdir)
131        return sc
132
133    def configure(self, path, version):
134        sc = 0
135        for d in ('cmt', 'mgr'):
136            p = os.path.join(path, d)
137            if os.path.isdir(p):
138                if not self.with_version_directory:
139                    sc += self.write(os.path.join(p,'version.cmt'), version)
140                if self.config:
141                    sc += self.generate(p)
142                return sc
143        return sc
144        #print >> sys.stderr, 'Cannot configure %s ' % (path, version)
145
146class Module(object):
147    def __init__(self, module):
148        self.module = module
149        self.init = False
150       
151class Checkout(object):
152    def __init__(self,
153                 url = None,
154                 trunk = None,
155                 tags = None,
156                 branches = None,
157                 version = None,
158                 version_dir = None,
159                 directory = None,
160                 offset = None,
161                 modules = []):
162        self.url = url
163        self.trunk = trunk
164        self.tags = tags
165        self.branches = branches
166        self.version = version
167        self.version_dir = version_dir
168        self.directory = directory
169        self.offset = offset
170        self.modules = modules
171        self.reposLayout()
172       
173    def reposLayout(self):
174        if self.url is None:
175            try:
176                self.url = os.environ['SVNROOT']
177            except KeyError:
178                pass
179        if self.trunk is None:
180            try:
181                self.trunk = os.environ['SVNTRUNK']
182            except KeyError:
183                self.trunk = 'trunk'
184        if self.tags is None:
185            try:
186                self.tags = os.environ['SVNTAGS']
187            except KeyError:
188                self.tags = 'tags'
189        if self.branches is None:
190            try:
191                self.branches = os.environ['SVNBRANCHES']
192            except KeyError:
193                self.branches = 'branches'
194
195    def cmtRepos(self):
196        self.url = 'https://svn.lal.in2p3.fr/projects/CMT'
197        self.trunk = 'HEAD'
198        self.tags= '.'
199        self.branches = '.'
200
201    def add(self, module):
202        self.modules.append(module)
203
204    def initialize(self, cmt_context, client_context):
205        sc = 0
206        self.head_revision = core.svn_opt_revision_t()
207        self.head_revision.kind = core.svn_opt_revision_head
208
209        for m in self.modules:
210            if urlparse.urlparse(m.module)[0] in ('http', 'https',
211                                                  'svn', 'svn+ssh', 'file'):
212                m.url = m.module
213                m.path = posixpath.basename(m.module)
214            elif posixpath.isabs(m.module):
215                m.url = urlparse.urljoin('file://', m.module)
216                m.path = posixpath.basename(m.module)
217            else:
218                if self.url is None:
219                    self.cmtRepos()
220
221                if self.offset is None:
222                    m.url = posixpath.join(self.url, m.module)
223                else:
224                    m.url = posixpath.join(self.url, self.offset, m.module)
225                m.path = os.path.join(*m.module.split(posixpath.sep))
226
227            if self.directory is not None:
228                m.path = os.path.normpath(self.directory)
229               
230            if self.version is None:
231                m.head = True
232                tags = core.svn_path_canonicalize(posixpath.join(m.url, self.tags))
233                try:
234                    #print 'client.ls2:', tags
235                    ls_tags = client.ls2(tags,
236                                         self.head_revision,
237                                         self.head_revision,
238                                         False,
239                                         client_context())
240                    rev_tag = dict([(ls_tags[p].created_rev, p) for p in ls_tags if ls_tags[p].kind == core.svn_node_dir])
241#                rev_latest = max(rev_tag.keys())
242#                tag_latest = rev_tag[rev_latest]
243                    m.version = rev_tag[max(rev_tag.keys())]
244                except core.SubversionException, e:
245                    print >> sys.stderr, e
246                    m.version = 'HEAD'
247                except ValueError, e: # max() arg is an empty sequence
248                    #print >> sys.stderr, e
249                    m.version = 'HEAD'
250            else:
251                m.head = False
252                m.version = self.version
253
254            if m.head:
255                m.URL = [posixpath.join(m.url, self.trunk)]
256            else:
257#                m.url = posixpath.join(m.url, self.tags, m.version)
258                m.URL = [posixpath.join(m.url, p, m.version)
259                         for p in (self.tags, self.branches)]
260                #m.URL = [posixpath.join(m.url, self.tags, m.version),
261                #         posixpath.join(m.url, self.branches, m.version)]
262            #m.url = core.svn_path_canonicalize(m.url)
263            m.URL = [core.svn_path_canonicalize(url) for url in m.URL]
264
265            if cmt_context.with_version_directory:
266                if self.version_dir is None:
267                    m.path = os.path.join(m.path, m.version)
268                else:
269                    m.path = os.path.join(m.path, self.version_dir)
270
271            m.init = True
272#            print m.URL, m.path, m.init
273           
274#        for m in self.modules:
275#            print m.url, m.path, m.init
276        return sc
277
278    def execute(self, cmt_context, client_context):
279        sc = 0
280
281        for m in self.modules:
282            if not m.init: continue
283            done = False
284            err = []
285            for url in m.URL:
286                try:
287                    #print 'client.checkout2:', url, m.path
288                    result_rev = client.checkout2(url,
289                                                  m.path,
290                                                  self.head_revision,
291                                                  self.head_revision,
292                                                  True,
293                                                  True,
294                                                  client_context())
295                except core.SubversionException, e:
296                    err.append(e)
297                    continue
298                done = True
299                break
300
301            if not done:
302                for e in err:
303                    print >> sys.stderr, e
304                    sc += 1
305                continue
306
307#            print 'Checked out revision %i.' % result_rev
308            scc = cmt_context.configure(m.path, m.version)
309            if scc != 0:
310                print >> sys.stderr, \
311                      '%s %s: configure returned %i.' % (m.path, m.version, scc)
312            sc += scc
313
314        return sc
315
316def main(argv=[__name__]):
317    self = os.path.basename(argv[0])
318    try:
319        opts, args = getopt.getopt(argv[1:],
320                                   "hr:d:o:",
321                                   ["help", "version", "version-tag=",
322                                    "version-dir=", "directory=",
323                                    "offset=", "no_config",
324                                    "with_version_directory",
325                                    "without_version_directory", "url="])
326    except getopt.error, e:
327        print >>sys.stderr, '%s: %s' % (self, str(e))
328        print >>sys.stderr, "Try '%s --help' for more information." % self
329        return 1
330
331    cmt_context = CmtContext()
332    checkout = Checkout()
333
334    for o, v in opts:
335        if o in ("-h", "--help"):
336            print sys.modules[__name__].__doc__
337            return 0
338        elif o in ("--version",):
339            print '%s %s (%s)' % (self, __version__, __date__)
340            print '%sWritten by %s.' % (os.linesep, __author__)
341            return 0
342        elif o in ("-r", "--version-tag"):
343            checkout.version = v
344        elif o in ("--version-dir",):
345            checkout.version_dir = v
346        elif o in ("-d", "--directory"):
347            checkout.directory = v
348        elif o in ("-o", "--offset"):
349            checkout.offset = v
350        elif o in ("--no_config",):
351            cmt_context.config = False
352        elif o in ("--without_version_directory",):
353            cmt_context.with_version_directory = False
354        elif o in ("--with_version_directory",):
355            cmt_context.with_version_directory = True
356        elif o in ("--url",):
357            checkout.url = v
358
359    if not args:
360        print >>sys.stderr, '%s: missing path argument' % self
361        print >>sys.stderr, "Try '%s --help' for more information." % self
362        return 1
363
364    for arg in args:
365        checkout.add(Module(arg))
366
367    client_context = ClientContext()
368    sci = checkout.initialize(cmt_context, client_context)
369    sce = checkout.execute(cmt_context, client_context)
370
371    if sci != 0 or sce !=0:
372        return 1
373    else:
374        return 0
375
376if __name__ == '__main__':
377    sys.exit(main(sys.argv))
Note: See TracBrowser for help on using the repository browser.