aboutsummaryrefslogtreecommitdiff
blob: e46d1dbccd3481c785a3b4ca11cbc95ac9766308 (plain)
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
import os
import subprocess

from roverlay      import config
from roverlay.util import keepenv


RSYNC_ENV = keepenv (
	'PATH',
	'USER',
	'LOGNAME',
	'RSYNC_PROXY',
	'RSYNC_PASSWORD',
)


# --recursive is not in the default opts, subdirs in CRAN/contrib are
# either R release (2.xx.x[-patches] or the package archive)
DEFAULT_RSYNC_OPTS =  (
	'--links',                  # copy symlinks as symlinks,
	'--safe-links',             #  but ignore links outside of tree
	'--times',                  #
	'--compress',               # FIXME: add lzo if necessary
	'--delete',                 #
	'--force',                  # allow deletion of non-empty dirs
	'--human-readable',         #
	'--stats',                  #
	'--chmod=ugo=r,u+w,Dugo+x', # 0755 for transferred dirs, 0644 for files
)

class RsyncJob ( object ):
	def __init__ (
		self, remote=None, distdir=None, run_now=True, extra_opts=None
	):
		self.remote     = remote
		self.distdir   = distdir
		self.extra_opts = None

		if run_now: self.run()
	# --- end of __init__ (...) ---

	def _rsync_argv ( self ):
		if self.remote is None or self.distdir is None:
			raise Exception ( "None in (remote,distdir)." )

		argv = [ 'rsync' ]

		argv.extend ( DEFAULT_RSYNC_OPTS )

		max_bw = config.get ( 'RSYNC_BWLIMIT', None )
		if max_bw is not None:
			argv.append ( '--bwlimit=%i' % max_bw )

		if self.extra_opts is not None:
			if isinstance ( self.extra_opts, str ) or \
				not hasattr ( self.extra_opts, '__iter__' )\
			:
				argv.append ( self.extra_opts )
			else:
				argv.extend ( self.extra_opts )

		argv.extend ( ( self.remote, self.distdir ) )

		return argv
	# --- end of _rsync_argv (...) ---

	def run ( self ):

		rsync_cmd = self._rsync_argv()

		os.makedirs ( self.distdir, exist_ok=True )

		# TODO pipe/log/.., running this in blocking mode until implemented

		proc = subprocess.Popen (
			rsync_cmd,
			stdin=None, stdout=None, stderr=None,
			env=RSYNC_ENV
		)

		if proc.communicate() != ( None, None ):
			raise AssertionError ( "expected None,None from communicate!" )

		self.returncode = proc.returncode

	# --- end of start (...) ---