def testDetachedRepo(self): repotest = os.path.join(self.tmpdir, 'repo-test') repotestclone = os.path.join(self.tmpdir, 'repo-test-clone') shelf = gitshelve.open(repository = repotest) text = "Hello, world!\n" shelf['foo.txt'] = text try: shelf.sync() gitshelve.git('clone', repotest, repotestclone) clonedfoo = os.path.join(repotestclone, 'foo.txt') try: self.assert_(os.path.isfile(clonedfoo)) data = open(clonedfoo) try: self.assertEqual(text, data.read()) finally: data.close() finally: if os.path.isdir(repotestclone): shutil.rmtree(repotestclone) finally: del shelf if os.path.isdir(repotest): shutil.rmtree(repotest)
def testDetachedRepo(self): repotest = os.path.join(self.tmpdir, 'repo-test') repotestclone = os.path.join(self.tmpdir, 'repo-test-clone') shelf = gitshelve.open(repository=repotest) text = "Hello, world!\n" shelf['foo.txt'] = text try: shelf.sync() gitshelve.git('clone', repotest, repotestclone) clonedfoo = os.path.join(repotestclone, 'foo.txt') try: self.assert_(os.path.isfile(clonedfoo)) data = open(clonedfoo) try: self.assertEqual(text, data.read()) finally: data.close() finally: if os.path.isdir(repotestclone): shutil.rmtree(repotestclone) finally: del shelf if os.path.isdir(repotest): shutil.rmtree(repotest)
def testDetachedRepo(self): shelf = gitshelve.open(repository = '/tmp/repo-test') text = "Hello, world!\n" shelf['foo.txt'] = text try: shelf.sync() gitshelve.git('clone', '/tmp/repo-test', '/tmp/repo-test-clone') try: self.assert_(os.path.isfile('/tmp/repo-test-clone/foo.txt')) data = open('/tmp/repo-test-clone/foo.txt') try: self.assertEqual(text, data.read()) finally: data.close() finally: if os.path.isdir('/tmp/repo-test-clone'): shutil.rmtree('/tmp/repo-test-clone') finally: del shelf if os.path.isdir('/tmp/repo-test'): shutil.rmtree('/tmp/repo-test')
def setUp(self): if os.name == 'nt': self.tmpdir = os.getenv('TEMP') else: self.tmpdir = '/tmp' try: gitshelve.git('branch', '-D', 'test') except: pass
def setUp(self): """Create a new git repository, cd to it, and create the initial commit""" self.gitDir = tempfile.mkdtemp() self.lastCWD = os.getcwd() os.chdir(self.gitDir) gitshelve.git('init') self.stream = StringIO() self.branch = 'git-tkt' self.gitTktFolder = GitTktFolder.GitTktFolder(name = 'active', branch = self.branch, fields = GitTkt.LoadFields(), outstream = self.stream)
def testInsertion(self): shelf = gitshelve.open('test') text = "Hello, this is a test\n" shelf['foo/bar/baz.c'] = text buf = StringIO() shelf.dump_objects(buf) self.assertEqual(buf.getvalue(), """tree: foo tree: bar blob: baz.c """) hash1 = shelf.commit('first\n') hash2 = shelf.commit('second\n') self.assertEqual(hash1, hash2) buf = StringIO() shelf.dump_objects(buf) self.assertEqual( """tree ca37be3e31987d8ece35001301c0b8f1fccbb888 tree 95b790693f3b5934c63d10b8b007e4758f6134a9: foo tree c03cdd65fa74c272bed2e9a48e3ed19402576e19: bar blob ea93d5cc5f34e13d2a55a5866b75e2c58993d253: baz.c """, buf.getvalue()) hash3 = shelf.current_head() self.assertEqual(hash1, hash3) commit = gitshelve.git('cat-file', 'commit', 'test', keep_newline=True) self.assert_(re.search('first\n$', commit)) data = gitshelve.git('cat-file', 'blob', 'test:foo/bar/baz.c', keep_newline=True) self.assertEqual(text, data) del shelf shelf = gitshelve.open('test') self.assertEqual( """tree ca37be3e31987d8ece35001301c0b8f1fccbb888 tree 95b790693f3b5934c63d10b8b007e4758f6134a9: foo tree c03cdd65fa74c272bed2e9a48e3ed19402576e19: bar blob ea93d5cc5f34e13d2a55a5866b75e2c58993d253: baz.c """, buf.getvalue()) self.assertEqual(text, shelf['foo/bar/baz.c']) del shelf
def setUp(self): """Create a new git repository, cd to it, and create the initial commit""" self.gitDir = tempfile.mkdtemp() self.lastCWD = os.getcwd() os.chdir(self.gitDir) gitshelve.git('init') self.stream = StringIO() self.branch = 'git-tkt' self.gittkt = GitTkt.GitTkt(branch = self.branch, nonInteractive = True, save = False, loadFolders = ['active'], outstream = self.stream)
def testInsertion(self): shelf = gitshelve.open('test') text = "Hello, this is a test\n" shelf['foo/bar/baz.c'] = text buf = StringIO() shelf.dump_objects(buf) self.assertEqual(buf.getvalue(), """tree: foo tree: bar blob: baz.c """) hash1 = shelf.commit('first\n') hash2 = shelf.commit('second\n') self.assertEqual(hash1, hash2) buf = StringIO() shelf.dump_objects(buf) self.assertEqual("""tree ca37be3e31987d8ece35001301c0b8f1fccbb888 tree 95b790693f3b5934c63d10b8b007e4758f6134a9: foo tree c03cdd65fa74c272bed2e9a48e3ed19402576e19: bar blob ea93d5cc5f34e13d2a55a5866b75e2c58993d253: baz.c """, buf.getvalue()) hash3 = shelf.current_head() self.assertEqual(hash1, hash3) commit = gitshelve.git('cat-file', 'commit', 'test', keep_newline = True) self.assert_(re.search('first\n$', commit)) data = gitshelve.git('cat-file', 'blob', 'test:foo/bar/baz.c', keep_newline = True) self.assertEqual(text, data) del shelf shelf = gitshelve.open('test') self.assertEqual("""tree ca37be3e31987d8ece35001301c0b8f1fccbb888 tree 95b790693f3b5934c63d10b8b007e4758f6134a9: foo tree c03cdd65fa74c272bed2e9a48e3ed19402576e19: bar blob ea93d5cc5f34e13d2a55a5866b75e2c58993d253: baz.c """, buf.getvalue()) self.assertEqual(text, shelf['foo/bar/baz.c']) del shelf
def testVersioning(self): shelf = gitshelve.open('test') text = "Hello, this is a test\n" shelf['foo/bar/baz1.c'] = text shelf.sync() buf = StringIO() shelf.dump_objects(buf) self.assertEqual( """tree 073629aeb0ef56a50a6cfcaf56da9b8393604b56 tree ce9d91f2da4ab3aa920cd5763be48b9aef76f999: foo tree 2e626f2ae629ea77618e84e79e1bfae1c473452e: bar blob ea93d5cc5f34e13d2a55a5866b75e2c58993d253: baz1.c """, buf.getvalue()) text = "Hello, this is a change\n" shelf['foo/bar/baz1.c'] = text shelf['foo/bar/baz2.c'] = text shelf.sync() buf = StringIO() shelf.dump_objects(buf) self.assertEqual( """tree c7c6fd4368460c645d0953349d5577d32f46115a tree 3936ea8daffe9eef0451b43205d6530374f8ffa3: foo tree 8f7bfca3bc33c93fb1a878bc79c2bb93d8f41730: bar blob fb54a7573d864d4b57ffcc8af37e7565e2ba4608: baz1.c blob fb54a7573d864d4b57ffcc8af37e7565e2ba4608: baz2.c """, buf.getvalue()) del shelf shelf = gitshelve.open('test') buf = StringIO() shelf.dump_objects(buf) self.assertEqual( """tree 3936ea8daffe9eef0451b43205d6530374f8ffa3: foo tree 8f7bfca3bc33c93fb1a878bc79c2bb93d8f41730: bar blob fb54a7573d864d4b57ffcc8af37e7565e2ba4608: baz1.c blob fb54a7573d864d4b57ffcc8af37e7565e2ba4608: baz2.c """, buf.getvalue()) self.assertEqual(text, shelf['foo/bar/baz1.c']) self.assertEqual(text, shelf['foo/bar/baz2.c']) log = gitshelve.git('log', 'test', keep_newline=True) self.assert_( re.match( """commit [0-9a-f]{40} Author: .+ Date: .+ commit [0-9a-f]{40} Author: .+ Date: .+ """, log))
def Folders(self,*args,**kwargs): try: data = gitshelve.git('ls-tree','--full-tree',self.branch) for line in data.split("\n"): matchObj = LS_TREE_RE.match(line) if matchObj is not None: self.outstream.write("%s\n"%matchObj.group(5)) return 0 except gitshelve.GitError as e: self.outstream.write("No folders found.\n") return 1
def testVersioning(self): shelf = gitshelve.open('test') text = "Hello, this is a test\n" shelf['foo/bar/baz1.c'] = text shelf.sync() buf = StringIO() shelf.dump_objects(buf) self.assertEqual("""tree 073629aeb0ef56a50a6cfcaf56da9b8393604b56 tree ce9d91f2da4ab3aa920cd5763be48b9aef76f999: foo tree 2e626f2ae629ea77618e84e79e1bfae1c473452e: bar blob ea93d5cc5f34e13d2a55a5866b75e2c58993d253: baz1.c """, buf.getvalue()) text = "Hello, this is a change\n" shelf['foo/bar/baz1.c'] = text shelf['foo/bar/baz2.c'] = text shelf.sync() buf = StringIO() shelf.dump_objects(buf) self.assertEqual("""tree c7c6fd4368460c645d0953349d5577d32f46115a tree 3936ea8daffe9eef0451b43205d6530374f8ffa3: foo tree 8f7bfca3bc33c93fb1a878bc79c2bb93d8f41730: bar blob fb54a7573d864d4b57ffcc8af37e7565e2ba4608: baz1.c blob fb54a7573d864d4b57ffcc8af37e7565e2ba4608: baz2.c """, buf.getvalue()) del shelf shelf = gitshelve.open('test') buf = StringIO() shelf.dump_objects(buf) self.assertEqual("""tree 3936ea8daffe9eef0451b43205d6530374f8ffa3: foo tree 8f7bfca3bc33c93fb1a878bc79c2bb93d8f41730: bar blob fb54a7573d864d4b57ffcc8af37e7565e2ba4608: baz1.c blob fb54a7573d864d4b57ffcc8af37e7565e2ba4608: baz2.c """, buf.getvalue()) self.assertEqual(text, shelf['foo/bar/baz1.c']) self.assertEqual(text, shelf['foo/bar/baz2.c']) log = gitshelve.git('log', 'test', keep_newline = True) self.assert_(re.match("""commit [0-9a-f]{40} Author: .+ Date: .+ commit [0-9a-f]{40} Author: .+ Date: .+ """, log))
def testGitbook(self): lsTreeRE = re.compile('(\d{6}) (tree|blob) ([0-9a-f]{40})\t(start|(.+))$') tree = gitshelve.git('ls-tree','--full-tree','-r', '-t','master') name = lsTreeRE.match(tree).group(3) shelf = gitshelve.gitshelve() b = gitshelve.gitbook(shelf, self.gitDir, name=name) self.assertEqual(repr(b), '<gitshelve.gitbook %s %s False>'%(self.gitDir,name)) data = 'temp' self.assertEqual(data,b.get_data()) b.data = None b.name = None with self.assertRaises(ValueError): b.get_data() b.set_data(data) self.assertEqual(data,b.get_data()) self.assertEqual(data,b.serialize_data(data)) self.assertEqual(data,b.deserialize_data(data)) newData = 'text' self.assertEqual(None,b.set_data(newData)) self.assertEqual(None,b.change_comment()) b.__setstate__({'data': 'something'}) self.assertEqual(b.__getstate__(),{'shelf': {}, 'path': self.gitDir, 'data': 'something', 'name': None})
def testGit(self): #run with verbose turned on gitshelve.verbose = True with NoStdStreams(): self.assertEqual(gitshelve.git('branch','-a'),"* master") tree = gitshelve.git('write-tree') #test with input in kwargs stdIn = 'first commit' result = "" with NoStdStreams(): result = gitshelve.git('commit-tree',tree,input = stdIn) self.assertRegex(result,'[0-9a-f]{40}') #from now on, run with verbose turned off gitshelve.verbose = False #test with repository in kwargs #-----repo exists rootRepoName = tempfile.mkdtemp() with self.assertRaises(gitshelve.GitError): gitshelve.git('ls-tree',repository = rootRepoName) #-----repo does not exist #----------first, cause git init to fail repoName = os.path.join(rootRepoName,"nonExistentRepo") with open(self.gitConfigFile,'w') as f: f.write("[push]\n\tdefault = trash") with self.assertRaises(gitshelve.GitError): gitshelve.git('write-tree',repository = repoName) shutil.rmtree(repoName) #----------fix config so git init won't fail with open(self.gitConfigFile,'w') as f: f.write(self.gitConfig) tree = gitshelve.git('write-tree',repository = repoName) self.assertRegex(tree,'[0-9a-f]{40}') cwdTree = gitshelve.git('ls-tree',tree) self.assertEqual('',cwdTree) shutil.rmtree(rootRepoName) #test with worktree in kwargs #-----repo exists rootRepoName = tempfile.mkdtemp() out = gitshelve.git('checkout','master', worktree = rootRepoName) self.assertEqual('D\tfile',out) #-----repo does not exist repoName = os.path.join(rootRepoName,'nonExistentRepo') out = gitshelve.git('checkout','master', worktree = repoName, keep_newline = True) self.assertEqual('D\tfile\n',out) shutil.rmtree(rootRepoName)
def tearDown(self): try: gitshelve.git('branch', '-D', 'test') except: pass
_cmd.help, ', '.join(_cmd.aliases) or 'None') return USAGE def initialize(): commands.import_commands() # check we are inside a git repo try: common.find_repo_root() except common.GitRepoNotFound, error: print error sys.exit(1) if len(gitshelve.git('branch').strip()) == 0: # user is trying to use gitissius on a repo that has no # branch, just exit print "Please create at least a branch before using gitissius" sys.exit(1) if not 'gitissius' in gitshelve.git('branch'): # no local gitissius branch exists # check if there is a remote remotes = re.findall("remotes/(.*)/gitissius", gitshelve.git('branch', '-a')) if len(remotes) == 1: # create a local copy gitshelve.git('branch', 'gitissius', remotes[0] + '/gitissius') elif len(remotes) > 1:
_cmd.help, ', '.join(_cmd.aliases) or 'None') return USAGE def initialize(): commands.import_commands() # check we are inside a git repo try: common.find_repo_root() except common.GitRepoNotFound, error: print error sys.exit(1) if len(gitshelve.git('branch').strip()) == 0: # user is trying to use gitissius on a repo that has no # branch, just exit print "Please create at least a branch before using gitissius" sys.exit(1) if not 'gitissius' in gitshelve.git('branch'): # no local gitissius branch exists # check if there is a remote if 'remotes/origin/gitissius' in gitshelve.git('branch', '-a'): # remote branch exists # create a local copy gitshelve.git('branch', 'gitissius', 'origin/gitissius') else: # save current branch name
', '.join(_cmd.aliases) or 'None') return USAGE def initialize(): commands.import_commands() # check we are inside a git repo try: common.find_repo_root() except common.GitRepoNotFound, error: print error sys.exit(1) if len(gitshelve.git('branch').strip()) == 0: # user is trying to use gitissius on a repo that has no # branch, just exit print "Please create at least a branch before using gitissius" sys.exit(1) if not 'gitissius' in gitshelve.git('branch'): # no local gitissius branch exists # check if there is a remote if 'remotes/origin/gitissius' in gitshelve.git('branch', '-a'): # remote branch exists # create a local copy gitshelve.git('branch', 'gitissius', 'origin/gitissius') else: # save current branch name
def setUp(self): try: gitshelve.git('branch', '-D', 'test') except: pass
def __MergeLocalNumbers(self,keepLocal = True): """ algorithm for merging local number ids: when merging, 3 changes can happen: 1. item added: can be added at the end and renumbered accordingly 2. item removed (archived or un-archived):can be removed numbers not reused unless it was the last item 3. item changed: happens if a renumbering occurred, in which the same rules as added can apply so, we want to fetch the latest from the remote. This will then be set to FETCH_HEAD. From that point, we can preform a 3-way merge. We diff the common ancestor with the 2 changed (FETCH_HEAD and self.branch). This can give us a list of added, removed, and changed With that list, we can remove everything that needs to be removed from the ancestor. The user can determine if they want the remote numbering to change or local numbering to change. Either way, we can then add the new tickets to the end, ensuring that niether uuids or local ids are duplicated. The result should be a merged list with tickets from both branches and a new local numbering scheme based on the numbering scheme the user wanted to keep. """ #update numbering #attempt to read it from te shelf self.__LoadNumMap() uuids = {} remoteNumMap = gitshelve.git('cat-file','-p', "FETCH_HEAD:%s"%(GitTkt.GITTKT_NUM_MAP_FILE)) parentRev = gitshelve.git('merge-base','FETCH_HEAD',self.branch) ancestorNumMap = gitshelve.git('cat-file','-p', "%s:%s"%(parentRev,GitTkt.GITTKT_NUM_MAP_FILE)) localLines = self.numMap.split("\n") remoteLines = remoteNumMap.split("\n") ancestorLines = ancestorNumMap.split("\n") diff = Differ() #find the differences localChanges=[x for x in list(diff.compare(ancestorLines,localLines)) if x[0] == '+' or x[0] =='-'] remoteChanges=[x for x in list(diff.compare(ancestorLines,remoteLines)) if x[0] == '+' or x[0] =='-'] #assume we keep remote numbering and alter local numbering firstChanges = remoteChanges secondChanges = localChanges first = 'remote' second = 'local' if keepLocal: first = 'local' second = 'remote' firstChanges = localChanges secondChanges = remoteChanges self.outstream.write("Applying %s changes after %s changes\n"%(second, first)) #determine the changes that will be needed removals = {} removals['local'] = OrderedDict() removals['remote'] = OrderedDict() additions = {} additions['local'] = OrderedDict() additions['remote'] = OrderedDict() ancestor = OrderedDict() for line in ancestorNumMap.split("\n"): if len(line) > 0: ancestor[line.split('\t')[1]] = line.split('\t')[0] elif line[0] == '+' and len(line) > 2: #this is an addition additions[line[2:].split('\t')[1]] = line[2:].split('\t')[0] for line in firstChanges: if line[0] == '-' and len(line) > 2: #this is a removal removals[first][line[2:].split('\t')[1]] = line[2:].split('\t')[0] elif line[0] == '+' and len(line) > 2: #this is an addition additions[first][line[2:].split('\t')[1]] = line[2:].split('\t')[0] for line in secondChanges: if line[0] == '-' and len(line) > 2: #this is a removal removals[second][line[2:].split('\t')[1]] = line[2:].split('\t')[0] elif line[0] == '+' and len(line) > 2: #this is an addition additions[second][line[2:].split('\t')[1]] = line[2:].split('\t')[0] #apply the changes output = OrderedDict() localIdsUsed = {} maxValues = max(additions[first].values(),additions[second].values()) lastLocalId = 0#int(max(maxValues)) for uuid,localId in ancestor.items(): if uuid in removals[first].keys(): self.outstream.write("Removed %sly: #%s (%s)\n"%(first,localId, uuid)) elif uuid in removals[second].keys(): self.outstream.write("Removed %sly: #%s (%s)\n"%(second,localId, uuid)) else: output[uuid] = localId localIdsUsed[localId] = "" lastLocalId = int(localId) useNewIds = False for uuid,localId in additions[first].items(): if uuid not in ancestor.keys() and \ uuid not in removals[first].keys() and \ uuid not in removals[second].keys() and \ uuid not in output.keys(): if not useNewIds and localId not in localIdsUsed.keys(): #we can use this id output[uuid] = localId self.outstream.write("Added %sly: #%s (%s)\n"%(first, localId,uuid)) localIdsUsed[localId] = "" lastLocalId = int(localId) else: useNewIds = True #this localId has been used. We need to set it to #the next number lastLocalId += 1 self.outstream.write("Added %sly: #%d [changed from #s]" "(%s)\n"%(first, lastLocalId, localId, uuid)) output[uuid] = str(lastLocalId) useNewIds = False for uuid,localId in additions[second].items(): if uuid not in ancestor.keys() and \ uuid not in removals[first].keys() and \ uuid not in removals[second].keys() and \ uuid not in output.keys(): if not useNewIds and localId not in localIdsUsed.keys(): #we can use this id output[uuid] = localId self.outstream.write("Added %sly: #%s (%s)\n"%(second, localId,uuid)) localIdsUsed[localId] = "" lastLocalId = int(localId) else: useNewIds = True #this localId has been used. We need to set it to #the next number lastLocalId += 1 self.outstream.write("Added %sly: #%d [changed from #%s]" "(%s)\n"%(second, lastLocalId, localId, uuid)) output[uuid] = str(lastLocalId)
def Pull(self,remote,remoteBranch,keepLocal = True): gitshelve.git('fetch',remote,remoteBranch) self.__mergeLocalNumbers(keepLocal) self.__mergeFiles()
def clone_uri(uri, destdir, origin_name): return gitshelve.git('clone', '--bare', '-o', origin_name, uri, destdir)
def merge(self, to_merge, dont_push=False): # make a tmp repository with a working tree # fetch, checkout, merge, push, delete # handle conflicts somehow... tmpdir = tempfile.mkdtemp(prefix='numbex-integration') tmprepo = os.path.join(tmpdir, '.git') integration = 'integration' had_conflicts = False self.log.info("starting merge") try: # create a local branch which we want to merge self.shelf.git('branch', integration, to_merge) gitshelve.git('init', repository=tmprepo) gitshelve.git('remote', 'add', 'origin', self.repodir, repository=tmprepo) gitshelve.git('fetch', 'origin', repository=tmprepo) # prepare to merge gitshelve.git('branch', self.repobranch, 'origin/'+self.repobranch, repository=tmprepo, worktree=tmpdir) gitshelve.git('checkout',self.repobranch, repository=tmprepo, worktree=tmpdir) # check if there aren't any overlaps before the merge self.log.info("checking for overlaps") db2 = NumbexRepo(self.repodir, self.get_pubkeys, integration) ovlself = self.check_overlaps() if ovlself: raise NumbexDBError("repository has overlapping ranges: %s"%ovlself) ovlother = db2.check_overlaps() if ovlother: raise NumbexDBError("remote %s has overlapping ranges: %s"%(to_merge, ovlother)) # find overlaps to delete later overlaps = self.check_overlaps2(db2) cwd = os.getcwd() # GIT_WORK_TREE doesn't work with git merge (bug in git?) os.chdir(tmpdir) try: mergeout = gitshelve.git('merge', 'origin/'+integration, repository=tmprepo, worktree=tmpdir) except gitshelve.GitError, e: # check if merge failed due to a conflict or something else if 'Automatic merge failed; fix conflicts and then commit the result.' in str(e): # handle conflicts here # git status fails with error code 128 for some reason # but generates required output status = gitshelve.git('status', repository=tmprepo, worktree=tmpdir, ignore_errors=True) for line in status.splitlines(): if line.startswith('# '): break filename, status = line.rsplit(':', 1) filename = filename.strip() status = status.strip() if status == 'needs merge': had_conflicts = True self.log.info("conflicted file: %s", filename) self.handle_merge(os.path.abspath(filename)) gitshelve.git('add', filename) # commit the result gitshelve.git('commit', '-m', 'merge. %s on %s'% (datetime.datetime.now(), socket.getfqdn()), repository=tmprepo, worktree=tmpdir) else: # not a merge conflict, abort raise except: self.log.exception("'git merge' failed:") raise finally: os.chdir(cwd) fixdb = NumbexRepo(tmprepo, self.get_pubkeys, self.repobranch) fixdb.fix_overlaps2(overlaps, db2) fixdb.sync() # push the results if not dont_push: gitshelve.git('push', 'origin', self.repobranch, repository=tmprepo) if had_conflicts: self.log.info("merge completed with conflicts resolved") else: self.log.info("merge completed without conflicts") return had_conflicts
def GetGitUser(): return "%s <%s>"%( gitshelve.git("config","user.name"), gitshelve.git("config","user.email"), )
', '.join(_cmd.aliases) or 'None') return USAGE def initialize(): commands.import_commands() # check we are inside a git repo try: common.find_repo_root() except common.GitRepoNotFound, error: print error sys.exit(1) if len(gitshelve.git('branch').strip()) == 0: # user is trying to use gitissius on a repo that has no # branch, just exit print "Please create at least a branch before using gitissius" sys.exit(1) if not 'gitissius' in gitshelve.git('branch'): # no local gitissius branch exists # check if there is a remote remotes = re.findall("remotes/(.*)/gitissius", gitshelve.git('branch', '-a')) if len(remotes) == 1: # create a local copy gitshelve.git('branch', 'gitissius', remotes[0] + '/gitissius')