##// END OF EJS Templates
shallowutil: introduce a helper function isenabled()...
Pulkit Goyal -
r40549:6f0b6905 default
parent child Browse files
Show More
@@ -216,6 +216,8 b" testedwith = 'ships-with-hg-core'"
216 repoclass = localrepo.localrepository
216 repoclass = localrepo.localrepository
217 repoclass._basesupported.add(constants.SHALLOWREPO_REQUIREMENT)
217 repoclass._basesupported.add(constants.SHALLOWREPO_REQUIREMENT)
218
218
219 isenabled = shallowutil.isenabled
220
219 def uisetup(ui):
221 def uisetup(ui):
220 """Wraps user facing Mercurial commands to swap them out with shallow
222 """Wraps user facing Mercurial commands to swap them out with shallow
221 versions.
223 versions.
@@ -236,8 +238,7 b' def uisetup(ui):'
236
238
237 # Prevent 'hg manifest --all'
239 # Prevent 'hg manifest --all'
238 def _manifest(orig, ui, repo, *args, **opts):
240 def _manifest(orig, ui, repo, *args, **opts):
239 if (constants.SHALLOWREPO_REQUIREMENT in repo.requirements
241 if (isenabled(repo) and opts.get('all')):
240 and opts.get('all')):
241 raise error.Abort(_("--all is not supported in a shallow repo"))
242 raise error.Abort(_("--all is not supported in a shallow repo"))
242
243
243 return orig(ui, repo, *args, **opts)
244 return orig(ui, repo, *args, **opts)
@@ -262,7 +263,7 b' def cloneshallow(orig, ui, repo, *args, '
262 if opts.get('shallow'):
263 if opts.get('shallow'):
263 repos = []
264 repos = []
264 def pull_shallow(orig, self, *args, **kwargs):
265 def pull_shallow(orig, self, *args, **kwargs):
265 if constants.SHALLOWREPO_REQUIREMENT not in self.requirements:
266 if not isenabled(self):
266 repos.append(self.unfiltered())
267 repos.append(self.unfiltered())
267 # set up the client hooks so the post-clone update works
268 # set up the client hooks so the post-clone update works
268 setupclient(self.ui, self.unfiltered())
269 setupclient(self.ui, self.unfiltered())
@@ -347,7 +348,7 b' def reposetup(ui, repo):'
347 ui.setconfig('hooks', 'commit.prefetch', wcpprefetch)
348 ui.setconfig('hooks', 'commit.prefetch', wcpprefetch)
348
349
349 isserverenabled = ui.configbool('remotefilelog', 'server')
350 isserverenabled = ui.configbool('remotefilelog', 'server')
350 isshallowclient = constants.SHALLOWREPO_REQUIREMENT in repo.requirements
351 isshallowclient = isenabled(repo)
351
352
352 if isserverenabled and isshallowclient:
353 if isserverenabled and isshallowclient:
353 raise RuntimeError("Cannot be both a server and shallow client.")
354 raise RuntimeError("Cannot be both a server and shallow client.")
@@ -396,7 +397,7 b' def onetimeclientsetup(ui):'
396
397
397 # prefetch files before update
398 # prefetch files before update
398 def applyupdates(orig, repo, actions, wctx, mctx, overwrite, labels=None):
399 def applyupdates(orig, repo, actions, wctx, mctx, overwrite, labels=None):
399 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
400 if isenabled(repo):
400 manifest = mctx.manifest()
401 manifest = mctx.manifest()
401 files = []
402 files = []
402 for f, args, msg in actions['g']:
403 for f, args, msg in actions['g']:
@@ -409,7 +410,7 b' def onetimeclientsetup(ui):'
409 # Prefetch merge checkunknownfiles
410 # Prefetch merge checkunknownfiles
410 def checkunknownfiles(orig, repo, wctx, mctx, force, actions,
411 def checkunknownfiles(orig, repo, wctx, mctx, force, actions,
411 *args, **kwargs):
412 *args, **kwargs):
412 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
413 if isenabled(repo):
413 files = []
414 files = []
414 sparsematch = repo.maybesparsematch(mctx.rev())
415 sparsematch = repo.maybesparsematch(mctx.rev())
415 for f, (m, actionargs, msg) in actions.iteritems():
416 for f, (m, actionargs, msg) in actions.iteritems():
@@ -428,7 +429,7 b' def onetimeclientsetup(ui):'
428 # Prefetch files before status attempts to look at their size and contents
429 # Prefetch files before status attempts to look at their size and contents
429 def checklookup(orig, self, files):
430 def checklookup(orig, self, files):
430 repo = self._repo
431 repo = self._repo
431 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
432 if isenabled(repo):
432 prefetchfiles = []
433 prefetchfiles = []
433 for parent in self._parents:
434 for parent in self._parents:
434 for f in files:
435 for f in files:
@@ -441,7 +442,7 b' def onetimeclientsetup(ui):'
441
442
442 # Prefetch the logic that compares added and removed files for renames
443 # Prefetch the logic that compares added and removed files for renames
443 def findrenames(orig, repo, matcher, added, removed, *args, **kwargs):
444 def findrenames(orig, repo, matcher, added, removed, *args, **kwargs):
444 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
445 if isenabled(repo):
445 files = []
446 files = []
446 parentctx = repo['.']
447 parentctx = repo['.']
447 for f in removed:
448 for f in removed:
@@ -454,7 +455,7 b' def onetimeclientsetup(ui):'
454 # prefetch files before mergecopies check
455 # prefetch files before mergecopies check
455 def computenonoverlap(orig, repo, c1, c2, *args, **kwargs):
456 def computenonoverlap(orig, repo, c1, c2, *args, **kwargs):
456 u1, u2 = orig(repo, c1, c2, *args, **kwargs)
457 u1, u2 = orig(repo, c1, c2, *args, **kwargs)
457 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
458 if isenabled(repo):
458 m1 = c1.manifest()
459 m1 = c1.manifest()
459 m2 = c2.manifest()
460 m2 = c2.manifest()
460 files = []
461 files = []
@@ -486,7 +487,7 b' def onetimeclientsetup(ui):'
486 def computeforwardmissing(orig, a, b, match=None):
487 def computeforwardmissing(orig, a, b, match=None):
487 missing = list(orig(a, b, match=match))
488 missing = list(orig(a, b, match=match))
488 repo = a._repo
489 repo = a._repo
489 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
490 if isenabled(repo):
490 mb = b.manifest()
491 mb = b.manifest()
491
492
492 files = []
493 files = []
@@ -513,7 +514,7 b' def onetimeclientsetup(ui):'
513 # repo can be None when running in chg:
514 # repo can be None when running in chg:
514 # - at startup, reposetup was called because serve is not norepo
515 # - at startup, reposetup was called because serve is not norepo
515 # - a norepo command like "help" is called
516 # - a norepo command like "help" is called
516 if repo and constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
517 if repo and isenabled(repo):
517 repo.fileservice.close()
518 repo.fileservice.close()
518 extensions.wrapfunction(dispatch, 'runcommand', runcommand)
519 extensions.wrapfunction(dispatch, 'runcommand', runcommand)
519
520
@@ -525,7 +526,7 b' def onetimeclientsetup(ui):'
525
526
526 # prevent strip from stripping remotefilelogs
527 # prevent strip from stripping remotefilelogs
527 def _collectbrokencsets(orig, repo, files, striprev):
528 def _collectbrokencsets(orig, repo, files, striprev):
528 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
529 if isenabled(repo):
529 files = list([f for f in files if not repo.shallowmatch(f)])
530 files = list([f for f in files if not repo.shallowmatch(f)])
530 return orig(repo, files, striprev)
531 return orig(repo, files, striprev)
531 extensions.wrapfunction(repair, '_collectbrokencsets', _collectbrokencsets)
532 extensions.wrapfunction(repair, '_collectbrokencsets', _collectbrokencsets)
@@ -576,16 +577,14 b' def onetimeclientsetup(ui):'
576 def filectx(orig, self, path, fileid=None, filelog=None):
577 def filectx(orig, self, path, fileid=None, filelog=None):
577 if fileid is None:
578 if fileid is None:
578 fileid = self.filenode(path)
579 fileid = self.filenode(path)
579 if (constants.SHALLOWREPO_REQUIREMENT in self._repo.requirements and
580 if (isenabled(self._repo) and self._repo.shallowmatch(path)):
580 self._repo.shallowmatch(path)):
581 return remotefilectx.remotefilectx(self._repo, path,
581 return remotefilectx.remotefilectx(self._repo, path,
582 fileid=fileid, changectx=self, filelog=filelog)
582 fileid=fileid, changectx=self, filelog=filelog)
583 return orig(self, path, fileid=fileid, filelog=filelog)
583 return orig(self, path, fileid=fileid, filelog=filelog)
584 extensions.wrapfunction(context.changectx, 'filectx', filectx)
584 extensions.wrapfunction(context.changectx, 'filectx', filectx)
585
585
586 def workingfilectx(orig, self, path, filelog=None):
586 def workingfilectx(orig, self, path, filelog=None):
587 if (constants.SHALLOWREPO_REQUIREMENT in self._repo.requirements and
587 if (isenabled(self._repo) and self._repo.shallowmatch(path)):
588 self._repo.shallowmatch(path)):
589 return remotefilectx.remoteworkingfilectx(self._repo,
588 return remotefilectx.remoteworkingfilectx(self._repo,
590 path, workingctx=self, filelog=filelog)
589 path, workingctx=self, filelog=filelog)
591 return orig(self, path, filelog=filelog)
590 return orig(self, path, filelog=filelog)
@@ -594,7 +593,7 b' def onetimeclientsetup(ui):'
594 # prefetch required revisions before a diff
593 # prefetch required revisions before a diff
595 def trydiff(orig, repo, revs, ctx1, ctx2, modified, added, removed,
594 def trydiff(orig, repo, revs, ctx1, ctx2, modified, added, removed,
596 copy, getfilectx, *args, **kwargs):
595 copy, getfilectx, *args, **kwargs):
597 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
596 if isenabled(repo):
598 prefetch = []
597 prefetch = []
599 mf1 = ctx1.manifest()
598 mf1 = ctx1.manifest()
600 for fname in modified + added + removed:
599 for fname in modified + added + removed:
@@ -652,7 +651,7 b' def getrenamedfn(repo, endrev=None):'
652 return getrenamed
651 return getrenamed
653
652
654 def walkfilerevs(orig, repo, match, follow, revs, fncache):
653 def walkfilerevs(orig, repo, match, follow, revs, fncache):
655 if not constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
654 if not isenabled(repo):
656 return orig(repo, match, follow, revs, fncache)
655 return orig(repo, match, follow, revs, fncache)
657
656
658 # remotefilelog's can't be walked in rev order, so throw.
657 # remotefilelog's can't be walked in rev order, so throw.
@@ -692,7 +691,7 b' def filelogrevset(orig, repo, subset, x)'
692 a slower, more accurate result, use ``file()``.
691 a slower, more accurate result, use ``file()``.
693 """
692 """
694
693
695 if not constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
694 if not isenabled(repo):
696 return orig(repo, subset, x)
695 return orig(repo, subset, x)
697
696
698 # i18n: "filelog" is a keyword
697 # i18n: "filelog" is a keyword
@@ -800,7 +799,7 b' def gcclient(ui, cachepath):'
800 # Protect against any repo or config changes that have happened since
799 # Protect against any repo or config changes that have happened since
801 # this repo was added to the repos file. We'd rather this loop succeed
800 # this repo was added to the repos file. We'd rather this loop succeed
802 # and too much be deleted, than the loop fail and nothing gets deleted.
801 # and too much be deleted, than the loop fail and nothing gets deleted.
803 if constants.SHALLOWREPO_REQUIREMENT not in repo.requirements:
802 if not isenabled(repo):
804 continue
803 continue
805
804
806 if not util.safehasattr(repo, 'name'):
805 if not util.safehasattr(repo, 'name'):
@@ -849,7 +848,7 b' def gcclient(ui, cachepath):'
849 ui.warn(_("warning: no valid repos in repofile\n"))
848 ui.warn(_("warning: no valid repos in repofile\n"))
850
849
851 def log(orig, ui, repo, *pats, **opts):
850 def log(orig, ui, repo, *pats, **opts):
852 if constants.SHALLOWREPO_REQUIREMENT not in repo.requirements:
851 if not isenabled(repo):
853 return orig(ui, repo, *pats, **opts)
852 return orig(ui, repo, *pats, **opts)
854
853
855 follow = opts.get('follow')
854 follow = opts.get('follow')
@@ -910,7 +909,7 b' def wcpprefetch(ui, repo, **kwargs):'
910 """Prefetches in background revisions specified by bgprefetchrevs revset.
909 """Prefetches in background revisions specified by bgprefetchrevs revset.
911 Does background repack if backgroundrepack flag is set in config.
910 Does background repack if backgroundrepack flag is set in config.
912 """
911 """
913 shallow = constants.SHALLOWREPO_REQUIREMENT in repo.requirements
912 shallow = isenabled(repo)
914 bgprefetchrevs = ui.config('remotefilelog', 'bgprefetchrevs')
913 bgprefetchrevs = ui.config('remotefilelog', 'bgprefetchrevs')
915 isready = readytofetch(repo)
914 isready = readytofetch(repo)
916
915
@@ -932,7 +931,7 b' def wcpprefetch(ui, repo, **kwargs):'
932 def pull(orig, ui, repo, *pats, **opts):
931 def pull(orig, ui, repo, *pats, **opts):
933 result = orig(ui, repo, *pats, **opts)
932 result = orig(ui, repo, *pats, **opts)
934
933
935 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
934 if isenabled(repo):
936 # prefetch if it's configured
935 # prefetch if it's configured
937 prefetchrevset = ui.config('remotefilelog', 'pullprefetch')
936 prefetchrevset = ui.config('remotefilelog', 'pullprefetch')
938 bgrepack = repo.ui.configbool('remotefilelog', 'backgroundrepack')
937 bgrepack = repo.ui.configbool('remotefilelog', 'backgroundrepack')
@@ -972,7 +971,7 b' def exchangepull(orig, repo, remote, *ar'
972 return orig(repo, remote, *args, **kwargs)
971 return orig(repo, remote, *args, **kwargs)
973
972
974 def _fileprefetchhook(repo, revs, match):
973 def _fileprefetchhook(repo, revs, match):
975 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
974 if isenabled(repo):
976 allfiles = []
975 allfiles = []
977 for rev in revs:
976 for rev in revs:
978 if rev == nodemod.wdirrev or rev is None:
977 if rev == nodemod.wdirrev or rev is None:
@@ -1068,7 +1067,7 b' def prefetch(ui, repo, *pats, **opts):'
1068
1067
1069 Return 0 on success.
1068 Return 0 on success.
1070 """
1069 """
1071 if not constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
1070 if not isenabled(repo):
1072 raise error.Abort(_("repo is not shallow"))
1071 raise error.Abort(_("repo is not shallow"))
1073
1072
1074 opts = resolveprefetchopts(ui, opts)
1073 opts = resolveprefetchopts(ui, opts)
@@ -92,7 +92,7 b' def debugindex(orig, ui, repo, file_=Non'
92 if (opts.get('changelog') or
92 if (opts.get('changelog') or
93 opts.get('manifest') or
93 opts.get('manifest') or
94 opts.get('dir') or
94 opts.get('dir') or
95 not constants.SHALLOWREPO_REQUIREMENT in repo.requirements or
95 not shallowutil.isenabled(repo) or
96 not repo.shallowmatch(file_)):
96 not repo.shallowmatch(file_)):
97 return orig(ui, repo, file_, **opts)
97 return orig(ui, repo, file_, **opts)
98
98
@@ -139,7 +139,7 b' def debugindex(orig, ui, repo, file_=Non'
139
139
140 def debugindexdot(orig, ui, repo, file_):
140 def debugindexdot(orig, ui, repo, file_):
141 """dump an index DAG as a graphviz dot file"""
141 """dump an index DAG as a graphviz dot file"""
142 if not constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
142 if not shallowutil.isenabled(repo):
143 return orig(ui, repo, file_)
143 return orig(ui, repo, file_)
144
144
145 r = buildtemprevlog(repo, os.path.basename(file_)[:-2])
145 r = buildtemprevlog(repo, os.path.basename(file_)[:-2])
@@ -132,7 +132,7 b' def onetimesetup(ui):'
132 def _walkstreamfiles(orig, repo):
132 def _walkstreamfiles(orig, repo):
133 if state.shallowremote:
133 if state.shallowremote:
134 # if we are shallow ourselves, stream our local commits
134 # if we are shallow ourselves, stream our local commits
135 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
135 if shallowutil.isenabled(repo):
136 striplen = len(repo.store.path) + 1
136 striplen = len(repo.store.path) + 1
137 readdir = repo.store.rawvfs.readdir
137 readdir = repo.store.rawvfs.readdir
138 visit = [os.path.join(repo.store.path, 'data')]
138 visit = [os.path.join(repo.store.path, 'data')]
@@ -166,7 +166,7 b' def onetimesetup(ui):'
166 continue
166 continue
167 yield x
167 yield x
168
168
169 elif constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
169 elif shallowutil.isenabled(repo):
170 # don't allow cloning from a shallow repo to a full repo
170 # don't allow cloning from a shallow repo to a full repo
171 # since it would require fetching every version of every
171 # since it would require fetching every version of every
172 # file in order to create the revlogs.
172 # file in order to create the revlogs.
@@ -193,8 +193,8 b' def onetimesetup(ui):'
193 # expose remotefilelog capabilities
193 # expose remotefilelog capabilities
194 def _capabilities(orig, repo, proto):
194 def _capabilities(orig, repo, proto):
195 caps = orig(repo, proto)
195 caps = orig(repo, proto)
196 if ((constants.SHALLOWREPO_REQUIREMENT in repo.requirements or
196 if (shallowutil.isenabled(repo) or ui.configbool('remotefilelog',
197 ui.configbool('remotefilelog', 'server'))):
197 'server')):
198 if isinstance(proto, _sshv1server):
198 if isinstance(proto, _sshv1server):
199 # legacy getfiles method which only works over ssh
199 # legacy getfiles method which only works over ssh
200 caps.append(constants.NETWORK_CAP_LEGACY_SSH_GETFILES)
200 caps.append(constants.NETWORK_CAP_LEGACY_SSH_GETFILES)
@@ -278,7 +278,7 b' def getfile(repo, proto, file, node):'
278 data is a compressed blob with revlog flag and ancestors information. See
278 data is a compressed blob with revlog flag and ancestors information. See
279 createfileblob for its content.
279 createfileblob for its content.
280 """
280 """
281 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
281 if shallowutil.isenabled(repo):
282 return '1\0' + _('cannot fetch remote files from shallow repo')
282 return '1\0' + _('cannot fetch remote files from shallow repo')
283 cachepath = repo.ui.config("remotefilelog", "servercachepath")
283 cachepath = repo.ui.config("remotefilelog", "servercachepath")
284 if not cachepath:
284 if not cachepath:
@@ -291,7 +291,7 b' def getfile(repo, proto, file, node):'
291 def getfiles(repo, proto):
291 def getfiles(repo, proto):
292 """A server api for requesting particular versions of particular files.
292 """A server api for requesting particular versions of particular files.
293 """
293 """
294 if constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
294 if shallowutil.isenabled(repo):
295 raise error.Abort(_('cannot fetch remote files from shallow repo'))
295 raise error.Abort(_('cannot fetch remote files from shallow repo'))
296 if not isinstance(proto, _sshv1server):
296 if not isinstance(proto, _sshv1server):
297 raise error.Abort(_('cannot fetch remote files over non-ssh protocol'))
297 raise error.Abort(_('cannot fetch remote files over non-ssh protocol'))
@@ -54,7 +54,7 b' def shallowgroup(cls, self, nodelist, rl'
54
54
55 class shallowcg1packer(changegroup.cgpacker):
55 class shallowcg1packer(changegroup.cgpacker):
56 def generate(self, commonrevs, clnodes, fastpathlinkrev, source):
56 def generate(self, commonrevs, clnodes, fastpathlinkrev, source):
57 if constants.SHALLOWREPO_REQUIREMENT in self._repo.requirements:
57 if shallowutil.isenabled(self._repo):
58 fastpathlinkrev = False
58 fastpathlinkrev = False
59
59
60 return super(shallowcg1packer, self).generate(commonrevs, clnodes,
60 return super(shallowcg1packer, self).generate(commonrevs, clnodes,
@@ -69,7 +69,7 b' class shallowcg1packer(changegroup.cgpac'
69 linknodes, commonrevs, source = args
69 linknodes, commonrevs, source = args
70 except ValueError:
70 except ValueError:
71 commonrevs, source, mfdicts, fastpathlinkrev, fnodes, clrevs = args
71 commonrevs, source, mfdicts, fastpathlinkrev, fnodes, clrevs = args
72 if constants.SHALLOWREPO_REQUIREMENT in self._repo.requirements:
72 if shallowutil.isenabled(self._repo):
73 repo = self._repo
73 repo = self._repo
74 if isinstance(repo, bundlerepo.bundlerepository):
74 if isinstance(repo, bundlerepo.bundlerepository):
75 # If the bundle contains filelogs, we can't pull from it, since
75 # If the bundle contains filelogs, we can't pull from it, since
@@ -91,7 +91,7 b' class shallowcg1packer(changegroup.cgpac'
91
91
92 def shouldaddfilegroups(self, source):
92 def shouldaddfilegroups(self, source):
93 repo = self._repo
93 repo = self._repo
94 if not constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
94 if not shallowutil.isenabled(repo):
95 return AllFiles
95 return AllFiles
96
96
97 if source == "push" or source == "bundle":
97 if source == "push" or source == "bundle":
@@ -139,7 +139,7 b' class shallowcg1packer(changegroup.cgpac'
139 yield delta
139 yield delta
140
140
141 def makechangegroup(orig, repo, outgoing, version, source, *args, **kwargs):
141 def makechangegroup(orig, repo, outgoing, version, source, *args, **kwargs):
142 if not constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
142 if not shallowutil.isenabled(repo):
143 return orig(repo, outgoing, version, source, *args, **kwargs)
143 return orig(repo, outgoing, version, source, *args, **kwargs)
144
144
145 original = repo.shallowmatch
145 original = repo.shallowmatch
@@ -168,7 +168,7 b' def makechangegroup(orig, repo, outgoing'
168 repo.shallowmatch = original
168 repo.shallowmatch = original
169
169
170 def addchangegroupfiles(orig, repo, source, revmap, trp, expectedfiles, *args):
170 def addchangegroupfiles(orig, repo, source, revmap, trp, expectedfiles, *args):
171 if not constants.SHALLOWREPO_REQUIREMENT in repo.requirements:
171 if not shallowutil.isenabled(repo):
172 return orig(repo, source, revmap, trp, expectedfiles, *args)
172 return orig(repo, source, revmap, trp, expectedfiles, *args)
173
173
174 files = 0
174 files = 0
@@ -30,6 +30,10 b' from . import constants'
30 if not pycompat.iswindows:
30 if not pycompat.iswindows:
31 import grp
31 import grp
32
32
33 def isenabled(repo):
34 """returns whether the repository is remotefilelog enabled or not"""
35 return constants.SHALLOWREPO_REQUIREMENT in repo.requirements
36
33 def getcachekey(reponame, file, id):
37 def getcachekey(reponame, file, id):
34 pathhash = hashlib.sha1(file).hexdigest()
38 pathhash = hashlib.sha1(file).hexdigest()
35 return os.path.join(reponame, pathhash[:2], pathhash[2:], id)
39 return os.path.join(reponame, pathhash[:2], pathhash[2:], id)
General Comments 0
You need to be logged in to leave comments. Login now