-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlink_mirror_project.py
164 lines (128 loc) · 5.65 KB
/
link_mirror_project.py
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# link_mirror_project.py
# osc plugin to create a link mirror of an OBS project
#
# Written by Aaron Bockover <[email protected]>
# Copyright 2009 Novell, Inc.
# Released under the MIT/X11 license.
#
@cmdln.option ('-t', '--to-apiurl', metavar='DIR',
help='URL of destination api server. Default is the source api server.')
@cmdln.option ('-p', '--source-proxy-name', metavar='PROXY',
help='Name of proxy "project" prefix the target server uses to access'
'projects in the source server. For instance, "openSUSE.org" if'
'openSUSE:Factory is accessible on the target server through'
'the project openSUSE.org:openSUSE:Factory.')
@cmdln.option ('-f', '--force', action='store_true',
help='Force the link mirror strategy without asking for confirmation.')
def do_link_mirror_project (self, subcmd, opts, *args):
"""${cmd_name}: Maintains a linkpac mirror of an OBS project
usage:
osc link_mirror_project SOURCEPRJ DESTPRJ
${cmd_option_list}
"""
args = slash_split (args)
if not args or len (args) != 2:
raise oscerr.WrongArgs ('Incorrect number of arguments.\n\n' \
+ self.get_cmd_help ('link_mirror_project'))
source_project, dest_project = args
source_apiurl = dest_apiurl = makeurl (conf.config['apiurl'], [])
source_proxy_name = ''
if opts.source_proxy_name:
source_proxy_name = opts.source_proxy_name + ':'
if opts.to_apiurl:
dest_apiurl = makeurl (opts.to_apiurl, [])
if source_project == dest_project and source_apiurl == dest_apiurl:
raise oscerr.WrongArgs ('Source and destination are the same.')
print 'Computing link mirror strategy...'
# if the projects do not exist, this will fail via exception
dest_packages = set (meta_get_packagelist (dest_apiurl, dest_project))
source_packages = set (meta_get_packagelist (source_apiurl, source_project))
# Compute what packages to link and remove
to_link = source_packages.difference (dest_packages)
to_remove = dest_packages.difference (source_packages)
if len (to_link) == 0 and len (to_remove) == 0:
print 'Mirror is in sync. Nothing to do.'
sys.exit (0)
# By default show the user what we'll do, and ask them to agree
if not opts.force:
self.print_and_confirm_strategy (source_apiurl, dest_apiurl,
source_project, dest_project, opts.source_proxy_name,
to_link, to_remove)
total_count = len (to_link) + len (to_remove)
current_count = 0
print 'Executing link mirror strategy...'
# Create links for new packages
for package in to_link:
current_count = current_count + 1
print 'LINK: %s (%s/%s)' % (package, current_count, total_count)
self.link_package (source_apiurl, dest_apiurl,
source_proxy_name, source_project, dest_project, package)
# Remove links for removed packages
for package in to_remove:
current_count = current_count + 1
print 'REMOVE: %s (%s/%s)' % (package, current_count, total_count)
delete_package (dest_apiurl, dest_project, package)
print 'Done.'
def link_package (self, source_apiurl, dest_apiurl, source_proxy_name,
source_project, dest_project, package):
# Create or update the destination link project from the source project
source_meta = show_package_meta (source_apiurl, source_project, package)
dest_meta = replace_pkg_meta (source_meta, package, dest_project)
u = makeurl (dest_apiurl, ['source', dest_project, package, '_meta'])
http_PUT (u, data = dest_meta)
link_data = '<link project="%s" package="%s"/>\n' % \
(source_proxy_name + source_project, package)
try:
u = makeurl (source_apiurl, ['source', source_project, package, '_link'])
tree = ET.parse (http_GET (u))
root = tree.getroot ()
link_cicount = root.get ('cicount')
link_project = root.get ('project')
link_package = root.get ('package')
if link_project == None or link_project == source_project:
link_data = '<link package="%s"' % link_package
if not link_cicount == None:
print ' (local link to %s with cicount=%s)' \
% (link_package, link_cicount)
link_data = link_data + ' cicount="%s"' % link_cicount
else:
print ' (local link to %s)' % link_package
link_data = link_data + '/>'
except:
pass
# Create/overwrite the destination _link file
u = makeurl (dest_apiurl, ['source', dest_project, package, '_link'])
http_PUT (u, data = link_data)
def print_and_confirm_strategy (self, source_apiurl, dest_apiurl,
source_project, dest_project, source_proxy_name, to_link, to_remove):
print
print """Link mirror configuration:
FROM: %s @ %s
TO: %s @ %s
VIA: %s
""" % (source_project, source_apiurl,
dest_project, dest_apiurl, source_proxy_name or '<no-proxy>')
to_link_count = len (to_link)
to_remove_count = len (to_remove)
if to_link_count > 0:
print 'New links to be created (%d):' % to_link_count
print
for package in to_link:
print ' %s' % package
if to_remove_count > 0:
print
if to_remove_count > 0:
print 'Stale links to be removed (%d):' % to_remove_count
print
for package in to_remove:
print ' %s' % package
print
while True:
print 'Continue? [Y/N]: ',
input = sys.stdin.readline ().strip ().lower ()
if input == 'y':
break
elif input == 'n':
print 'Aborted.'
sys.exit (1)
print