def commit(self, message=''): """ Create a new revision of this blueprint in the local Git repository. Include the blueprint JSON and any source archives referenced by the JSON. """ git.init() refname = 'refs/heads/{0}'.format(self.name) parent = git.rev_parse(refname) # Start with an empty index every time. Specifically, clear out # source tarballs from the parent commit. if parent is not None: for mode, type, sha, pathname in git.ls_tree(git.tree(parent)): git.git('update-index', '--force-remove', pathname) # Add `blueprint.json` to the index. f = open('blueprint.json', 'w') f.write(self.dumps()) f.close() git.git('update-index', '--add', os.path.abspath('blueprint.json')) # Add source tarballs to the index. for filename in self.sources.itervalues(): git.git('update-index', '--add', os.path.abspath(filename)) # Add `/etc/blueprintignore` and `~/.blueprintignore` to the index. # Since adding extra syntax to this file, it no longer makes sense # to store it as `.gitignore`. f = open('blueprintignore', 'w') for pathname in ('/etc/blueprintignore', os.path.expanduser('~/.blueprintignore')): try: f.write(open(pathname).read()) except IOError: pass f.close() git.git('update-index', '--add', os.path.abspath('blueprintignore')) # Write the index to Git's object store. tree = git.write_tree() # Write the commit and update the tip of the branch. self._commit = git.commit_tree(tree, message, parent) git.git('update-ref', refname, self._commit)
def _mirror_one(self, branch, input_work_dir, output_reference): self.debug('*********** start work for branch %s -> %s' % ( branch, self.output_branch_name(branch), )) if not self._need_to_mirror(branch, input_work_dir, output_reference): return True with tempdir.tempdir() as tmpdir: output_work_dir = os.path.join(tmpdir, 'output') start_commit, new_branch = self._prepare_output_git( branch, input_work_dir, output_work_dir, output_reference) commits = self._find_commits(branch, start_commit, input_work_dir, output_work_dir) os.chdir(tmpdir) committed_anything = False last_failure = None try: # In this case we're already done, the loop below would be skipped # completely, but we can't even calculate the (unnecessary) # prep_prev_commit and similar, nor do we really have to check out # the code to generate nothing. However, if it's a new branch we # may have to push it out, so go through the "finally:" segment of # the code (and hence have the return statement within the "try:" # block. # The output tree is correct since self._prepare_output_git() will # leave it at the commit it wanted to start generating from (even # if there's nothing to generate, it doesn't consider that.) if len(commits) == 0: return True prep_prev_commit = Commit( git.rev_parse(commits[0].tree_id + '^', tree=input_work_dir), input_work_dir) self._checkout(prep_prev_commit.tree_id, input_work_dir) submodules = self._submodule_status(input_work_dir) for commit in commits: prev_commit = prep_prev_commit prep_prev_commit = commit if not self._create_output(branch, commit, input_work_dir, output_work_dir, start_commit, new_branch): if last_failure is None: last_failure = commit continue if last_failure: last_failure_shortlog = git.shortlog( last_failure, commit) else: last_failure_shortlog = None git.add('.', tree=output_work_dir) prev_submodules = submodules submodules = self._submodule_status(input_work_dir) if self.is_modified(tree=output_work_dir): parents = [git.rev_parse('HEAD', tree=output_work_dir)] tree_id = git.write_tree(tree=output_work_dir) for s in submodules: if not s in prev_submodules: continue if prev_submodules[s] != submodules[s]: parents += self._handle_submodule( branch, prev_commit, s, prev_submodules[s], submodules[s], input_work_dir, output_work_dir, start_commit, new_branch) self._commit_modified(commit, input_work_dir, output_work_dir, last_failure_shortlog, tree_id, parents) committed_anything = True elif new_branch and self.always_commit_new_branch: self._commit_new_branch(commit, output_work_dir) committed_anything = True new_branch = False last_failure = None git.set_note(self.notes_branch, 'HEAD', commit.tree_id, tree=output_work_dir, env=self._commit_env()) except Abort: return False finally: # if necessary, push to the server from the output_work_dir git.set_origin_url(self._output_tree, gitdir=output_work_dir) if committed_anything or new_branch: git.push(opts=[ '-q', 'origin', 'HEAD:' + self.output_branch_name(branch) ], tree=output_work_dir) git.push(opts=[ '-q', '-f', 'origin', 'refs/notes/' + self.notes_branch ], tree=output_work_dir) return True