1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# vim: set sw=4 sts=4 et :
# Copyright: 2008 Gentoo Foundation
# Author(s): Nirbheek Chauhan <nirbheek.chauhan@gmail.com>
# License: GPL-2
#
# Immortal lh!
#
import os, subprocess, shutil
import os.path as osp
from .. import const
class Syncer(object):
"""
Sync stuff
"""
def __init__(self, scheme='git', uri=const.JOBTAGE_URI, rev=None, destdir=const.JOBTAGE_DIR):
"""
Default is to sync the jobtage tree from the default location.
@param destdir: Destination directory; sync *contents* into destdir
@scheme destdir: string
@param uri: Uri where to sync from
@scheme uri: string
@param rev: SCM Revision to export. Default is latest
@scheme rev: string
@param scheme: The URI scheme
@scheme scheme: string
"""
self.destdir = destdir
self.scheme = scheme
self.command = Command(scheme, uri, rev, destdir)
def _is_repo(self):
"""
Broad classification of repos into three types based on their behaviour
1. Same commands for init & sync (eg: rsync)
- return 1 (init)
2. Different init & sync commands (eg: git)
- Detect if self.destdir is a repo
* Return 2 if it is (sync), 3 if not (rmtree && init)
3. No concept of sync (eg: bzr-export)
- Delete self.destdir before 'sync'
* return 3 (rmtree && init)
"""
if self.scheme in ['rsync']:
return 1
elif self.scheme in ['git', 'bzr']:
result = subprocess.Popen('cd %s; git-rev-parse' % self.destdir, shell=True)
if result != 0:
return 3
return 2
elif self.scheme in ['git-export', 'bzr-export']:
return 3
def sync(self):
"""
Sync self.uri contents to self.destdir
"""
if osp.exists(self.destdir):
if not osp.isdir(self.destdir):
# FIXME: Custom exceptions
raise '"%s" exists and is not a directory' % self.destdir
result = self._is_repo()
if result == '1':
self.command.run('init')
elif result == '2':
self.command.run('sync')
elif result == '3':
raise 'destdir: \"%s\" exists and is not a %s tree' % self.destdir, self.scheme
else:
if not osp.exists(osp.dirname(self.destdir)):
# Create parents
os.makedirs(osp.dirname(self.destdir))
self.command.run('init')
class Command(object):
"""Command to use for each uri scheme and action"""
def __init__(self, scheme, uri, rev, destdir):
if not uri.endswith('/'):
uri += '/'
if not rev:
if scheme == 'bzr-export':
rev = 'last:1'
elif scheme == 'git-export':
rev = 'HEAD'
self.scheme = scheme
self.uri = uri
self.rev = rev
self.destdir = destdir
def _get_args(self, action='init'):
if self.scheme == 'bzr':
if action == 'init':
return 'bzr branch "%s" "%s"' % (self.uri, self.destdir)
elif action == 'sync':
return 'bzr pull --overwrite "%s" -d "%s"' % (self.uri, self.destdir)
elif self.scheme == 'bzr-export':
return 'bzr export -r"%s" "%s" "%s"' % (self.rev, self.destdir, self.uri)
elif self.scheme == 'git':
if action == 'init':
return 'git clone "%s" "%s"' % (self.uri, self.destdir)
if action == 'sync':
return 'cd "%s"; git reset --hard HEAD; git pull "%s"' % (self.destdir, self.uri)
elif self.scheme == 'git-export':
return 'git-archive --prefix="%s/" --remote="%s" "%s" | tar x -C "%s"' % (osp.basename(self.destdir), self.uri, self.rev, osp.dirname(self.destdir))
elif self.scheme == 'rsync':
command = 'rsync -a --delete "%s" "%s"' % (self.uri, self.destdir)
if const.VERBOSE:
command += ' --verbose'
return command
raise "Unknown scheme: %s" % self.scheme
def run(self, action):
"""Run a sync command"""
args = self._get_args(action=action)
subprocess.check_call(args, shell=True)
|