]>
Commit | Line | Data |
---|---|---|
a7db4597 AM |
1 | commit 29ab16f193cf3ebccb0c044b98f2ba9be98c3090 |
2 | Author: Arkadiusz Miśkiewicz <arekm@maven.pl> | |
3 | Date: Sun Nov 23 00:32:46 2014 +0100 | |
4 | ||
5 | Make updateall off by default. | |
6 | ||
7 | Turn updateall to off by default so 'git pld pull' will only checkout | |
8 | packages that were fetched at this session. If you want old behaviour | |
9 | use 'git pld pull --all'. | |
10 | ||
11 | diff --git a/slug.py b/slug.py | |
12 | index d083cf4..fa8fd89 100755 | |
13 | --- a/slug.py | |
14 | +++ b/slug.py | |
15 | @@ -274,7 +274,7 @@ default_options['fetch'] = {'branch': '[*]', 'prune': False, 'newpkgs': False, ' | |
16 | ||
17 | pull = subparsers.add_parser('pull', help='git-pull in all existing repositories', parents=[common_fetchoptions], | |
18 | formatter_class=argparse.RawDescriptionHelpFormatter) | |
19 | -pull.add_argument('--all', help='update local branches in all repositories', dest='updateall', action='store_true', default=True) | |
20 | +pull.add_argument('--all', help='update local branches in all repositories', dest='updateall', action='store_true', default=False) | |
21 | pull.add_argument('--noall', help='update local branches only when something has been fetched', dest='updateall', action='store_false', default=True) | |
22 | newpkgsopt = pull.add_mutually_exclusive_group() | |
23 | newpkgsopt.add_argument('-n', '--newpkgs', help='download packages that do not exist on local side', | |
24 | ||
25 | commit da9abb0e6d7ef1a1440e7f5ac4ad4dbf5538dc99 | |
26 | Author: Arkadiusz Miśkiewicz <arekm@maven.pl> | |
27 | Date: Sun Nov 23 00:28:22 2014 +0100 | |
28 | ||
29 | Add --newpkgs/--nonewpkgs to pull command. | |
30 | ||
31 | Allow 'git pld pull --newpkgs' to also fetch and pull new packages. Off | |
32 | by default. | |
33 | ||
34 | diff --git a/slug.py b/slug.py | |
35 | index da9c050..d083cf4 100755 | |
36 | --- a/slug.py | |
37 | +++ b/slug.py | |
38 | @@ -276,8 +276,12 @@ pull = subparsers.add_parser('pull', help='git-pull in all existing repositories | |
39 | formatter_class=argparse.RawDescriptionHelpFormatter) | |
40 | pull.add_argument('--all', help='update local branches in all repositories', dest='updateall', action='store_true', default=True) | |
41 | pull.add_argument('--noall', help='update local branches only when something has been fetched', dest='updateall', action='store_false', default=True) | |
42 | +newpkgsopt = pull.add_mutually_exclusive_group() | |
43 | +newpkgsopt.add_argument('-n', '--newpkgs', help='download packages that do not exist on local side', | |
44 | + action='store_true') | |
45 | +newpkgsopt.add_argument('-nn', '--nonewpkgs', help='do not download new packages', dest='newpkgs', action='store_false') | |
46 | pull.set_defaults(func=pull_packages, branch='[*]', prune=False, newpkgs=False, omitexisting=False) | |
47 | -default_options['pull'] = {'branch': ['*'], 'prune': False, 'newpkgs': False, 'omitexisting': False} | |
48 | +default_options['pull'] = {'branch': ['*'], 'prune': False, 'omitexisting': False} | |
49 | ||
50 | checkout =subparsers.add_parser('checkout', help='checkout repositories', parents=[common_fetchoptions], | |
51 | formatter_class=argparse.RawDescriptionHelpFormatter) | |
52 | ||
53 | commit b1096c634ea9b262bd791863d68e2aed3847078d | |
54 | Author: Arkadiusz Miśkiewicz <arekm@maven.pl> | |
55 | Date: Sun Nov 23 00:18:38 2014 +0100 | |
56 | ||
57 | Parallelize fetching, checking out, cloning. | |
58 | ||
59 | Parallelize fetching, checking out, cloning using multiprocessing | |
60 | module. | |
61 | ||
62 | By default use number of parallel processes equal to number of | |
63 | system CPUs (use old value, 4, as fallback). | |
64 | ||
65 | Also replace thread based ThreadFetch() with the same multiprocessing | |
66 | mechanism as above for consistency. | |
67 | ||
68 | diff --git a/slug.py b/slug.py | |
69 | index 69bd3b9..da9c050 100755 | |
70 | --- a/slug.py | |
71 | +++ b/slug.py | |
cac91f77 | 72 | @@ -7,26 +7,18 @@ import os |
bd32afc7 AM |
73 | import shutil |
74 | import subprocess | |
75 | import queue | |
76 | -import threading | |
77 | - | |
78 | +import multiprocessing | |
79 | import argparse | |
80 | ||
81 | import signal | |
82 | import configparser | |
83 | ||
84 | +from multiprocessing import Pool as WorkerPool | |
85 | + | |
86 | from git_slug.gitconst import GITLOGIN, GITSERVER, GIT_REPO, GIT_REPO_PUSH, REMOTE_NAME, REMOTEREFS | |
87 | from git_slug.gitrepo import GitRepo, GitRepoError | |
88 | from git_slug.refsdata import GitArchiveRefsData, NoMatchedRepos, RemoteRefsError | |
89 | ||
90 | -class Store(): | |
91 | - def __init__(self): | |
92 | - self.lock = threading.Lock() | |
93 | - self.items = [] | |
94 | - | |
95 | - def put(self, item): | |
96 | - with self.lock: | |
97 | - self.items.append(item) | |
98 | - | |
99 | class UnquoteConfig(configparser.ConfigParser): | |
100 | def get(self, section, option, **kwargs): | |
101 | value = super().get(section, option, **kwargs) | |
cac91f77 | 102 | @@ -43,25 +35,15 @@ class DelAppend(argparse._AppendAction): |
bd32afc7 AM |
103 | item.append(values) |
104 | setattr(namespace, self.dest, item) | |
105 | ||
106 | -class ThreadFetch(threading.Thread): | |
107 | - def __init__(self, queue, output, pkgdir, depth=0): | |
108 | - threading.Thread.__init__(self) | |
109 | - self.queue = queue | |
110 | - self.packagesdir = pkgdir | |
111 | - self.depth = depth | |
112 | - self.output = output | |
113 | - | |
114 | - def run(self): | |
115 | - while True: | |
116 | - (gitrepo, ref2fetch) = self.queue.get() | |
117 | - try: | |
118 | - (stdout, stderr) = gitrepo.fetch(ref2fetch, self.depth) | |
119 | - if stderr != b'': | |
120 | - print('------', gitrepo.gdir[:-len('.git')], '------\n' + stderr.decode('utf-8')) | |
121 | - self.output.put(gitrepo) | |
122 | - except GitRepoError as e: | |
123 | - print('------', gitrepo.gdir[:-len('.git')], '------\n', e) | |
124 | - self.queue.task_done() | |
125 | +def cpu_count(): | |
126 | + try: | |
127 | + return multiprocessing.cpu_count() | |
128 | + except NotImplementedError: | |
129 | + pass | |
130 | + return 4 | |
131 | + | |
132 | +def pool_worker_init(): | |
133 | + signal.signal(signal.SIGINT, signal.SIG_IGN) | |
134 | ||
135 | def readconfig(path): | |
136 | config = UnquoteConfig(delimiters='=', interpolation=None, strict=False) | |
cac91f77 | 137 | @@ -114,18 +96,19 @@ def getrefs(*args): |
bd32afc7 AM |
138 | sys.exit(2) |
139 | return refs | |
140 | ||
141 | +def fetch_package(gitrepo, ref2fetch, options): | |
142 | + try: | |
143 | + (stdout, stderr) = gitrepo.fetch(ref2fetch, options.depth) | |
144 | + if stderr != b'': | |
145 | + print('------', gitrepo.gdir[:-len('.git')], '------\n' + stderr.decode('utf-8')) | |
146 | + return gitrepo | |
147 | + except GitRepoError as e: | |
148 | + print('------', gitrepo.gdir[:-len('.git')], '------\n', e) | |
149 | + | |
150 | def fetch_packages(options, return_all=False): | |
151 | - fetch_queue = queue.Queue() | |
152 | - updated_repos = Store() | |
153 | - for i in range(options.jobs): | |
154 | - t = ThreadFetch(fetch_queue, updated_repos, options.packagesdir, options.depth) | |
155 | - t.setDaemon(True) | |
156 | - t.start() | |
157 | - | |
158 | - signal.signal(signal.SIGINT, signal.SIG_DFL) | |
159 | - | |
160 | refs = getrefs(options.branch, options.repopattern) | |
161 | print('Read remotes data') | |
162 | + args = [] | |
163 | for pkgdir in sorted(refs.heads): | |
164 | gitdir = os.path.join(options.packagesdir, pkgdir, '.git') | |
165 | if not os.path.isdir(gitdir): | |
a7db4597 | 166 | @@ -143,9 +126,18 @@ def fetch_packages(options, return_all=False): |
bd32afc7 AM |
167 | ref2fetch.append('+{}:{}/{}'.format(ref, REMOTEREFS, ref[len('refs/heads/'):])) |
168 | if ref2fetch: | |
169 | ref2fetch.append('refs/notes/*:refs/notes/*') | |
170 | - fetch_queue.put((gitrepo, ref2fetch)) | |
171 | + args.append((gitrepo, ref2fetch, options)) | |
a7db4597 AM |
172 | |
173 | - fetch_queue.join() | |
bd32afc7 AM |
174 | + pool = WorkerPool(options.jobs, pool_worker_init) |
175 | + try: | |
176 | + updated_repos = pool.starmap(fetch_package, args) | |
177 | + except KeyboardInterrupt: | |
178 | + pool.terminate() | |
179 | + else: | |
180 | + pool.close() | |
181 | + pool.join() | |
a7db4597 | 182 | + |
bd32afc7 AM |
183 | + updated_repos = list(filter(None, updated_repos)) |
184 | ||
185 | if options.prune: | |
186 | refs = getrefs('*') | |
a7db4597 | 187 | @@ -158,26 +150,60 @@ def fetch_packages(options, return_all=False): |
bd32afc7 AM |
188 | if return_all: |
189 | return refs.heads | |
190 | else: | |
191 | - return updated_repos.items | |
192 | + return updated_repos | |
193 | + | |
194 | +def checkout_package(repo, options): | |
195 | + try: | |
196 | + repo.checkout(options.checkout) | |
197 | + except GitRepoError as e: | |
198 | + print('Problem with checking branch {} in repo {}: {}'.format(options.checkout, repo.gdir, e), file=sys.stderr) | |
199 | ||
200 | def checkout_packages(options): | |
201 | if options.checkout is None: | |
202 | options.checkout = "/".join([REMOTE_NAME, options.branch[0]]) | |
203 | fetch_packages(options) | |
204 | refs = getrefs(options.branch, options.repopattern) | |
205 | + repos = [] | |
206 | for pkgdir in sorted(refs.heads): | |
207 | - repo = GitRepo(os.path.join(options.packagesdir, pkgdir)) | |
208 | - try: | |
209 | - repo.checkout(options.checkout) | |
210 | - except GitRepoError as e: | |
211 | - print('Problem with checking branch {} in repo {}: {}'.format(options.checkout, repo.gdir, e), file=sys.stderr) | |
cac91f77 AM |
212 | + repos.append(GitRepo(os.path.join(options.packagesdir, pkgdir))) |
213 | + pool = WorkerPool(options.jobs) | |
bd32afc7 AM |
214 | + try: |
215 | + pool.starmap(checkout_package, zip(repos, [options] * len(repos))) | |
216 | + except KeyboardInterrupt: | |
217 | + pool.terminate() | |
218 | + else: | |
219 | + pool.close() | |
220 | + pool.join() | |
221 | + | |
222 | +def clone_package(repo, options): | |
223 | + try: | |
224 | + repo.checkout('master') | |
225 | + except GitRepoError as e: | |
226 | + print('Problem with checking branch master in repo {}: {}'.format(repo.gdir, e), file=sys.stderr) | |
227 | ||
228 | def clone_packages(options): | |
229 | - for repo in fetch_packages(options): | |
230 | - try: | |
231 | - repo.checkout('master') | |
232 | - except GitRepoError as e: | |
233 | - print('Problem with checking branch master in repo {}: {}'.format(repo.gdir, e), file=sys.stderr) | |
234 | + repos = fetch_packages(options) | |
cac91f77 | 235 | + pool = WorkerPool(options.jobs) |
bd32afc7 AM |
236 | + try: |
237 | + pool.starmap(clone_package, zip(repos, [options] * len(repos))) | |
238 | + except KeyboardInterrupt: | |
239 | + pool.terminate() | |
240 | + else: | |
241 | + pool.close() | |
242 | + pool.join() | |
243 | + | |
244 | +def pull_package(gitrepo, options): | |
245 | + directory = os.path.basename(gitrepo.wtree) | |
246 | + try: | |
247 | + (out, err) = gitrepo.commandexc(['rev-parse', '-q', '--verify', '@{u}']) | |
248 | + sha1 = out.decode().strip() | |
249 | + (out, err) = gitrepo.commandexc(['rebase', sha1]) | |
250 | + for line in out.decode().splitlines(): | |
251 | + print(directory,":",line) | |
252 | + except GitRepoError as e: | |
253 | + for line in e.args[0].splitlines(): | |
254 | + print("{}: {}".format(directory,line)) | |
255 | + pass | |
256 | ||
257 | def pull_packages(options): | |
258 | repolist = [] | |
cac91f77 | 259 | @@ -189,19 +215,14 @@ def pull_packages(options): |
bd32afc7 AM |
260 | else: |
261 | repolist = fetch_packages(options, False) | |
262 | print('--------Pulling------------') | |
263 | - for gitrepo in repolist: | |
264 | - directory = os.path.basename(gitrepo.wtree) | |
265 | - try: | |
266 | - (out, err) = gitrepo.commandexc(['rev-parse', '-q', '--verify', '@{u}']) | |
267 | - sha1 = out.decode().strip() | |
268 | - (out, err) = gitrepo.commandexc(['rebase', sha1]) | |
269 | - for line in out.decode().splitlines(): | |
270 | - print(directory,":",line) | |
271 | - except GitRepoError as e: | |
272 | - for line in e.args[0].splitlines(): | |
273 | - print("{}: {}".format(directory,line)) | |
274 | - pass | |
275 | - | |
276 | + pool = WorkerPool(options.jobs, pool_worker_init) | |
277 | + try: | |
278 | + pool.starmap(pull_package, zip(repolist, [options] * len(repolist))) | |
279 | + except KeyboardInterrupt: | |
280 | + pool.terminate() | |
281 | + else: | |
282 | + pool.close() | |
283 | + pool.join() | |
284 | ||
285 | def list_packages(options): | |
286 | refs = getrefs(options.branch, options.repopattern) | |
a7db4597 | 287 | @@ -213,7 +234,7 @@ common_options.add_argument('-d', '--packagesdir', help='local directory with gi |
bd32afc7 AM |
288 | default=os.path.expanduser('~/rpm/packages')) |
289 | ||
290 | common_fetchoptions = argparse.ArgumentParser(add_help=False, parents=[common_options]) | |
291 | -common_fetchoptions.add_argument('-j', '--jobs', help='number of threads to use', default=4, type=int) | |
292 | +common_fetchoptions.add_argument('-j', '--jobs', help='number of threads to use', default=cpu_count(), type=int) | |
293 | common_fetchoptions.add_argument('repopattern', nargs='*', default = ['*']) | |
294 | common_fetchoptions.add_argument('--depth', help='depth of fetch', default=0) | |
295 | ||
a7db4597 AM |
296 | |
297 | commit fac30722a98a4d6300822fd3f790ce1fa48e7d83 | |
298 | Author: Arkadiusz Miśkiewicz <arekm@maven.pl> | |
299 | Date: Sun Nov 23 00:15:10 2014 +0100 | |
300 | ||
301 | check_remote(): Add support to packed refs database. | |
302 | ||
303 | check_remote() did not handle git packed refs database. That made | |
304 | fetch_packages() to always fetch packages even if we already had | |
305 | them fetched. | |
306 | ||
307 | Supporting packed refs database fixes this problem. | |
308 | ||
309 | diff --git a/git_slug/gitrepo.py b/git_slug/gitrepo.py | |
310 | index 5234deb..d9f88ee 100644 | |
311 | --- a/git_slug/gitrepo.py | |
312 | +++ b/git_slug/gitrepo.py | |
313 | @@ -82,12 +82,21 @@ class GitRepo: | |
314 | 'refs/notes/*:refs/notes/*']) | |
315 | ||
316 | def check_remote(self, ref, remote=REMOTE_NAME): | |
317 | + localref = EMPTYSHA1 | |
318 | ref = ref.replace(REFFILE, os.path.join('remotes', remote)) | |
319 | try: | |
320 | with open(os.path.join(self.gdir, ref), 'r') as f: | |
321 | localref = f.readline().strip() | |
322 | except IOError: | |
323 | - localref = EMPTYSHA1 | |
324 | + try: | |
325 | + with open(os.path.join(self.gdir, 'packed-refs')) as f: | |
326 | + for line in f: | |
327 | + line_data = line.split() | |
328 | + if len(line_data) == 2 and line_data[1] == ref: | |
329 | + localref = line_data[0].strip() | |
330 | + break | |
331 | + except IOError: | |
332 | + pass | |
333 | return localref | |
334 | ||
335 | def showfile(self, filename, ref="/".join([REMOTE_NAME, "master"])): |