X-Git-Url: https://git.distorted.org.uk/~mdw/stgit/blobdiff_plain/f338c3c088774601c6cd422bfac635c4187266c4..8e29bcd2fd67066143b88de8829130c6af043e2f:/stgit/git.py diff --git a/stgit/git.py b/stgit/git.py index e05f99a..c1c20c7 100644 --- a/stgit/git.py +++ b/stgit/git.py @@ -75,10 +75,23 @@ class Commit: def get_committer(self): return self.__committer +# dictionary of Commit objects, used to avoid multiple calls to git +__commits = dict() # # Functions # +def get_commit(id_hash): + """Commit objects factory. Save/look-up them in the __commits + dictionary + """ + if id_hash in __commits: + return __commits[id_hash] + else: + commit = Commit(id_hash) + __commits[id_hash] = commit + return commit + def get_conflicts(): """Return the list of file conflicts """ @@ -91,6 +104,14 @@ def get_conflicts(): else: return None +def _input(cmd, file_desc): + p = popen2.Popen3(cmd) + for line in file_desc: + p.tochild.write(line) + p.tochild.close() + if p.wait(): + raise GitException, '%s failed' % str(cmd) + def _output(cmd): p=popen2.Popen3(cmd) string = p.fromchild.read() @@ -265,7 +286,7 @@ def commit(message, files = [], parents = [], allowempty = False, raise GitException, 'No changes to commit' # check for unresolved conflicts - if not first and len(filter(lambda x: x[0] not in ['M', 'N', 'D'], + if not first and len(filter(lambda x: x[0] not in ['M', 'N', 'A', 'D'], cache_files)) != 0: raise GitException, 'Commit failed: unresolved conflicts' @@ -283,7 +304,7 @@ def commit(message, files = [], parents = [], allowempty = False, rm_files=[] m_files=[] for f in cache_files: - if f[0] == 'N': + if f[0] in ['N', 'A']: add_files.append(f[1]) elif f[0] == 'D': rm_files.append(f[1]) @@ -356,6 +377,7 @@ def status(files = [], modified = False, new = False, deleted = False, if modified: filestat.append('M') if new: + filestat.append('A') filestat.append('N') if deleted: filestat.append('D') @@ -410,36 +432,37 @@ def files(rev1, rev2): return str.rstrip() -def checkout(files = [], force = False): +def checkout(files = [], tree_id = None, force = False): """Check out the given or all files """ - git_flags = 'git-checkout-cache -q -u' + if tree_id and __run('git-read-tree -m', [tree_id]) != 0: + raise GitException, 'Failed git-read-tree -m %s' % tree_id + + checkout_cmd = 'git-checkout-cache -q -u' if force: - git_flags += ' -f' + checkout_cmd += ' -f' if len(files) == 0: - git_flags += ' -a' + checkout_cmd += ' -a' else: - git_flags += ' --' + checkout_cmd += ' --' - if __run(git_flags, files) != 0: + if __run(checkout_cmd, files) != 0: raise GitException, 'Failed git-checkout-cache' def switch(tree_id): """Switch the tree to the given id """ - to_delete = filter(lambda x: x[0] == 'N', __tree_status(tree_id = tree_id)) + to_delete = filter(lambda x: x[0] in ['N', 'A'], + __tree_status(tree_id = tree_id)) - if __run('git-read-tree -m', [tree_id]) != 0: - raise GitException, 'Failed git-read-tree -m %s' % tree_id - - checkout(force = True) + checkout(tree_id = tree_id, force = True) __set_head(tree_id) # checkout doesn't remove files for fs in to_delete: os.remove(fs[1]) -def fetch(location, head = None, tag = None): +def pull(location, head = None, tag = None): """Fetch changes from the remote repository. At the moment, just use the 'git fetch' scripts """ @@ -449,7 +472,25 @@ def fetch(location, head = None, tag = None): elif tag: args += ['tag', tag] - if __run('git fetch', args) != 0: + if __run('git pull', args) != 0: raise GitException, 'Failed "git fetch %s"' % location - return read_string(os.path.join(base_dir, 'FETCH_HEAD')) +def apply_patch(filename = None): + """Apply a patch onto the current index. There must not be any + local changes in the tree, otherwise the command fails + """ + os.system('git-update-cache --refresh > /dev/null') + + if filename: + if __run('git-apply --index', [filename]) != 0: + raise GitException, 'Patch does not apply cleanly' + else: + _input('git-apply --index', sys.stdin) + +def clone(repository, local_dir): + """Clone a remote repository. At the moment, just use the + 'git clone' script + """ + if __run('git clone', [repository, local_dir]) != 0: + raise GitException, 'Failed "git clone %s %s"' \ + % (repository, local_dir)