OLD | NEW |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Gnumd (Git NUMber Daemon): Adds metadata to git commits as they land in | 5 """Gnumd (Git NUMber Daemon): Adds metadata to git commits as they land in |
6 a primary repo. | 6 a primary repo. |
7 | 7 |
8 This is a simple daemon which takes commits pushed to a pending ref, alters | 8 This is a simple daemon which takes commits pushed to a pending ref, alters |
9 their message with metadata, and then pushes the altered commits to a parallel | 9 their message with metadata, and then pushes the altered commits to a parallel |
10 ref. | 10 ref. |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 i += 1 | 255 i += 1 |
256 | 256 |
257 if i > 0: | 257 if i > 0: |
258 logging.warn('Catching up pending_tag %r (was %d behind)', pending_tag, i) | 258 logging.warn('Catching up pending_tag %r (was %d behind)', pending_tag, i) |
259 new_tag_val = new_commits[i-1] | 259 new_tag_val = new_commits[i-1] |
260 if content_of(new_tag_val) != content_of(real_ref.commit): | 260 if content_of(new_tag_val) != content_of(real_ref.commit): |
261 LOGGER.error('Content of new tag %r does not match content of %r!', | 261 LOGGER.error('Content of new tag %r does not match content of %r!', |
262 new_tag_val.hsh, real_ref.commit.hsh) | 262 new_tag_val.hsh, real_ref.commit.hsh) |
263 return [] | 263 return [] |
264 new_commits = new_commits[i:] | 264 new_commits = new_commits[i:] |
265 pending_tag.fast_forward_push(new_tag_val) | 265 pending_tag.repo.fast_forward_push({pending_tag: new_tag_val}) |
266 | 266 |
267 if not new_commits: | 267 if not new_commits: |
268 LOGGER.warn('Tag was lagging for %r by %d, but no new commits are pending', | 268 LOGGER.warn('Tag was lagging for %r by %d, but no new commits are pending', |
269 real_ref, len(new_commits)) | 269 real_ref, len(new_commits)) |
270 return [] | 270 return [] |
271 | 271 |
272 return new_commits | 272 return new_commits |
273 | 273 |
274 | 274 |
275 def process_ref(real_ref, pending_tag, new_commits, clock=time): | 275 def process_ref(real_ref, pending_tag, new_commits, clock=time): |
(...skipping 19 matching lines...) Expand all Loading... |
295 @type real_ref: git2.Ref | 295 @type real_ref: git2.Ref |
296 @type pending_tag: git2.Ref | 296 @type pending_tag: git2.Ref |
297 @type new_commits: [git2.Commit] | 297 @type new_commits: [git2.Commit] |
298 @kind clock: implements .time(), used for testing determinisim. | 298 @kind clock: implements .time(), used for testing determinisim. |
299 """ | 299 """ |
300 # TODO(iannucci): use push --force-with-lease to reset pending to the real | 300 # TODO(iannucci): use push --force-with-lease to reset pending to the real |
301 # ref? | 301 # ref? |
302 # TODO(iannucci): The ACL rejection message for the real ref should point | 302 # TODO(iannucci): The ACL rejection message for the real ref should point |
303 # users to the pending ref. | 303 # users to the pending ref. |
304 assert content_of(pending_tag.commit) == content_of(real_ref.commit) | 304 assert content_of(pending_tag.commit) == content_of(real_ref.commit) |
| 305 assert real_ref.repo == pending_tag.repo |
| 306 repo = real_ref.repo |
305 real_parent = real_ref.commit | 307 real_parent = real_ref.commit |
306 for commit in new_commits: | 308 for commit in new_commits: |
307 assert content_of(commit.parent) == content_of(real_parent) | 309 assert content_of(commit.parent) == content_of(real_parent) |
308 synth_commit = synthesize_commit(commit, real_parent, real_ref, clock) | 310 synth_commit = synthesize_commit(commit, real_parent, real_ref, clock) |
309 | 311 |
310 # TODO(iannucci): do multi-ref atomic push here. | 312 logging.info( |
311 logging.info('Pushing synthesized commit %r for %r', synth_commit.hsh, | 313 'Pushing synthesized commit %r for %r and pending_tag %r', |
312 commit.hsh) | 314 synth_commit.hsh, commit.hsh, pending_tag) |
313 real_ref.fast_forward_push(synth_commit) | 315 repo.fast_forward_push({ |
| 316 real_ref: synth_commit, |
| 317 pending_tag: commit, |
| 318 }) |
314 | 319 |
315 logging.debug('Pushing pending_tag %r', pending_tag) | |
316 pending_tag.fast_forward_push(commit) | |
317 real_parent = synth_commit | 320 real_parent = synth_commit |
318 | 321 |
319 | 322 |
320 def process_repo(repo, cref, clock=time): | 323 def process_repo(repo, cref, clock=time): |
321 """Execute a single pass over a fetched Repo. | 324 """Execute a single pass over a fetched Repo. |
322 | 325 |
323 Will call |process_ref| for every branch indicated by the enabled_refglobs | 326 Will call |process_ref| for every branch indicated by the enabled_refglobs |
324 config option. | 327 config option. |
325 """ | 328 """ |
326 pending_tag_prefix = cref['pending_tag_prefix'] | 329 pending_tag_prefix = cref['pending_tag_prefix'] |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 LOGGER.error('%s %s', e.__class__.__name__, e) | 366 LOGGER.error('%s %s', e.__class__.__name__, e) |
364 except Exception: # pragma: no cover | 367 except Exception: # pragma: no cover |
365 LOGGER.exception('Uncaught exception while processing %r', real_ref) | 368 LOGGER.exception('Uncaught exception while processing %r', real_ref) |
366 | 369 |
367 | 370 |
368 def inner_loop(repo, cref, clock=time): | 371 def inner_loop(repo, cref, clock=time): |
369 LOGGER.debug('fetching %r', repo) | 372 LOGGER.debug('fetching %r', repo) |
370 repo.run('fetch', stdout=sys.stdout, stderr=sys.stderr) | 373 repo.run('fetch', stdout=sys.stdout, stderr=sys.stderr) |
371 cref.evaluate() | 374 cref.evaluate() |
372 process_repo(repo, cref, clock) | 375 process_repo(repo, cref, clock) |
OLD | NEW |