def _walkonetree(self, tree, match, subdir): for te in tree: # TODO: can we prune dir walks with the matcher? realname = subdir + pycompat.fsencode(te.name) if te.type == pygit2.GIT_OBJ_TREE: for inner in self._walkonetree( self._git_repo[te.id], match, realname + b'/' ): yield inner elif match(realname): yield pycompat.fsencode(realname)
def _iterativediff(t1, t2, subdir): """compares two trees and appends new tree nodes to examine to the stack""" if t1 is None: t1 = {} if t2 is None: t2 = {} for e1 in t1: realname = subdir + pycompat.fsencode(e1.name) if e1.type == pygit2.GIT_OBJ_TREE: try: e2 = t2[e1.name] if e2.type != pygit2.GIT_OBJ_TREE: e2 = None except KeyError: e2 = None stack.append((realname + b'/', e1, e2)) else: n1, fl1 = self.find(realname) try: e2 = t2[e1.name] n2, fl2 = other.find(realname) except KeyError: e2 = None n2, fl2 = (None, b'') if e2 is not None and e2.type == pygit2.GIT_OBJ_TREE: stack.append((realname + b'/', None, e2)) if not match(realname): continue if n1 != n2 or fl1 != fl2: result[realname] = ((n1, fl1), (n2, fl2)) elif clean: result[realname] = None for e2 in t2: if e2.name in t1: continue realname = subdir + pycompat.fsencode(e2.name) if e2.type == pygit2.GIT_OBJ_TREE: stack.append((realname + b'/', None, e2)) elif match(realname): n2, fl2 = other.find(realname) result[realname] = ((None, b''), (n2, fl2))
def main(): op = optparse.OptionParser() op.add_option('-d', '--daemon', action='store_true') op.add_option('--daemon-postexec', action='append') op.add_option('-p', '--port', type=int, default=8025) op.add_option('-a', '--address', default='localhost') op.add_option('--pid-file', metavar='FILE') op.add_option('--tls', choices=['none', 'smtps'], default='none') op.add_option('--certificate', metavar='FILE') opts, args = op.parse_args() if opts.tls == 'smtps' and not opts.certificate: op.error('--certificate must be specified') addr = (opts.address, opts.port) def init(): if opts.tls == 'none': dummysmtpserver(addr) else: dummysmtpsecureserver(addr, opts.certificate) log('listening at %s:%d\n' % addr) server.runservice( bytesvars(opts), initfn=init, runfn=run, runargs=[pycompat.sysexecutable, pycompat.fsencode(__file__)] + pycompat.sysargv[1:])
def active(self): h = self.gitrepo.references['HEAD'] if not isinstance(h.target, str) or not h.target.startswith( _BMS_PREFIX ): return None return pycompat.fsencode(h.target[len(_BMS_PREFIX) :])
def names(self, node): r = [] for ref in self.gitrepo.listall_references(): if not ref.startswith(_BMS_PREFIX): continue if self.gitrepo.references[ref].peel().id.raw != node: continue r.append(pycompat.fsencode(ref[len(_BMS_PREFIX) :])) return r
def get_index( gitrepo, logfn=lambda x: None, progress_factory=lambda *args, **kwargs: None ): cachepath = os.path.join( pycompat.fsencode(gitrepo.path), b'..', b'.hg', b'cache' ) if not os.path.exists(cachepath): os.makedirs(cachepath) dbpath = os.path.join(cachepath, b'git-commits.sqlite') db = _createdb(dbpath) # TODO check against gitrepo heads before doing a full index # TODO thread a ui.progress call into this layer _index_repo(gitrepo, db, logfn, progress_factory) return db
def createPack(self, revisions=None): """Creates and returns a historypack containing the specified revisions. `revisions` is a list of tuples, where each tuple contains a filanem, node, p1node, p2node, and linknode. """ if revisions is None: revisions = [("filename", self.getFakeHash(), nullid, nullid, self.getFakeHash(), None)] packdir = pycompat.fsencode(self.makeTempDir()) packer = historypack.mutablehistorypack(uimod.ui(), packdir, version=2) for filename, node, p1, p2, linknode, copyfrom in revisions: packer.add(filename, node, p1, p2, linknode, copyfrom) path = packer.close() return historypack.historypack(path)
def walk(self, match, subrepos, unknown, ignored, full=True): # TODO: we need to use .status() and not iterate the index, # because the index doesn't force a re-walk and so `hg add` of # a new file without an intervening call to status will # silently do nothing. r = {} cwd = self.getcwd() for path, status in self.git.status().items(): if path.startswith('.hg/'): continue path = pycompat.fsencode(path) if not match(path): continue # TODO construct the stat info from the status object? try: s = os.stat(os.path.join(cwd, path)) except OSError as e: if e.errno != errno.ENOENT: raise continue r[path] = s return r
def testcachedunfifoobar(repo): name = repo.filtername if name is None: name = '' val = 100 + len(name) unficalllog.append(val) return val #plug them on repo localrepo.localrepository.testcachedfoobar = testcachedfoobar localrepo.localrepository.testcachedunfifoobar = testcachedunfifoobar # Create an empty repo and instantiate it. It is important to run # these tests on the real object to detect regression. repopath = pycompat.fsencode(os.path.join(os.environ['TESTTMP'], 'repo')) assert subprocess.call( pycompat.rapply(procutil.tonativestr, [b'hg', b'init', repopath])) == 0 ui = uimod.ui.load() repo = hg.repository(ui, path=repopath).unfiltered() print('') print('=== property cache ===') print('') print('calllog:', calllog) print('cached value (unfiltered):', vars(repo).get('testcachedfoobar', 'NOCACHE')) print('') print('= first access on unfiltered, should do a call')
def matches(self, match): for x in self.git.index: p = pycompat.fsencode(x.path) if match(p): yield p
def _checklink(self): return util.checklink(os.path.dirname(pycompat.fsencode( self.git.path)))
def getcwd(self): # TODO is this a good way to do this? return os.path.dirname( os.path.dirname(pycompat.fsencode(self.git.path)))
def status(self, match, subrepos, ignored, clean, unknown): listclean = clean # TODO handling of clean files - can we get that from git.status()? modified, added, removed, deleted, unknown, ignored, clean = ( [], [], [], [], [], [], [], ) gstatus = self.git.status() for path, status in gstatus.items(): path = pycompat.fsencode(path) if not match(path): continue if status == pygit2.GIT_STATUS_IGNORED: if path.endswith(b'/'): continue ignored.append(path) elif status in ( pygit2.GIT_STATUS_WT_MODIFIED, pygit2.GIT_STATUS_INDEX_MODIFIED, pygit2.GIT_STATUS_WT_MODIFIED | pygit2.GIT_STATUS_INDEX_MODIFIED, ): modified.append(path) elif status == pygit2.GIT_STATUS_INDEX_NEW: added.append(path) elif status == pygit2.GIT_STATUS_WT_NEW: unknown.append(path) elif status == pygit2.GIT_STATUS_WT_DELETED: deleted.append(path) elif status == pygit2.GIT_STATUS_INDEX_DELETED: removed.append(path) else: raise error.Abort(b'unhandled case: status for %r is %r' % (path, status)) if listclean: observed = set(modified + added + removed + deleted + unknown + ignored) index = self.git.index index.read() for entry in index: path = pycompat.fsencode(entry.path) if not match(path): continue if path in observed: continue # already in some other set if path[-1] == b'/': continue # directory clean.append(path) # TODO are we really always sure of status here? return ( False, scmutil.status(modified, added, removed, deleted, unknown, ignored, clean), )
parser.add_option('-f', '--foreground', dest='foreground', action='store_true', help='do not start the HTTP server in the background') parser.add_option('--daemon-postexec', action='append') (options, args) = parser.parse_args() signal.signal(signal.SIGTERM, lambda x, y: sys.exit(0)) if options.foreground and options.logfile: parser.error("options --logfile and --foreground are mutually " "exclusive") if options.foreground and options.pid: parser.error("options --pid and --foreground are mutually exclusive") opts = { b'pid_file': options.pid, b'daemon': not options.foreground, b'daemon_postexec': options.daemon_postexec } service = simplehttpservice(options.host, options.port) runargs = [sys.executable, __file__] + sys.argv[1:] runargs = [pycompat.fsencode(a) for a in runargs] server.runservice(opts, initfn=service.init, runfn=service.run, logfile=options.logfile, runargs=runargs)
def makeTempDir(self): tempdir = tempfile.mkdtemp() self.tempdirs.append(tempdir) return pycompat.fsencode(tempdir)
TESTDIR = os.environ["TESTDIR"] BUNDLEPATH = os.path.join(TESTDIR, 'bundles', 'test-no-symlinks.hg') # only makes sense to test on os which supports symlinks if not getattr(os, "symlink", False): sys.exit(80) # SKIPPED_STATUS defined in run-tests.py u = uimod.ui.load() # hide outer repo hg.peer(u, {}, b'.', create=True) # unbundle with symlink support hg.peer(u, {}, b'test0', create=True) repo = hg.repository(u, b'test0') commands.unbundle(u, repo, pycompat.fsencode(BUNDLEPATH), update=True) # wait a bit, or the status call wont update the dirstate time.sleep(1) commands.status(u, repo) # now disable symlink support -- this is what os.symlink would do on a # non-symlink file system def symlink_failure(src, dst): raise OSError(1, "Operation not permitted") os.symlink = symlink_failure def islink_failure(path): return False os.path.islink = islink_failure # dereference links as if a Samba server has exported this to a
def __iter__(self): for r in self.gitrepo.listall_references(): if r.startswith(_BMS_PREFIX): yield pycompat.fsencode(r[len(_BMS_PREFIX) :])
manifest, pycompat, repository, revlog, sshpeer, statichttprepo, ui as uimod, unionrepo, vfs as vfsmod, wireprotoserver, wireprototypes, wireprotov1peer, wireprotov2server, ) rootdir = pycompat.fsencode( os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))) def checkzobject(o, allowextra=False): """Verify an object with a zope interface.""" ifaces = zi.providedBy(o) if not ifaces: print('%r does not provide any zope interfaces' % o) return # Run zope.interface's built-in verification routine. This verifies that # everything that is supposed to be present is present. for iface in ifaces: ziverify.verifyObject(iface, o) if allowextra:
def before(self): # Get registered archives self.archives = [ i.rstrip(b'\n') for i in self.runlines0(b'archives', b'-n') ] if self.execmd == b'tla': output = self.run0(b'tree-version', self.path) else: output = self.run0(b'tree-version', b'-d', self.path) self.treeversion = output.strip() # Get name of temporary directory version = self.treeversion.split(b'/') self.tmppath = os.path.join(pycompat.fsencode(tempfile.gettempdir()), b'hg-%s' % version[1]) # Generate parents dictionary self.parents[None] = [] treeversion = self.treeversion child = None while treeversion: self.ui.status(_(b'analyzing tree version %s...\n') % treeversion) archive = treeversion.split(b'/')[0] if archive not in self.archives: self.ui.status( _(b'tree analysis stopped because it points to ' b'an unregistered archive %s...\n') % archive) break # Get the complete list of revisions for that tree version output, status = self.runlines(b'revisions', b'-r', b'-f', treeversion) self.checkexit(status, b'failed retrieving revisions for %s' % treeversion) # No new iteration unless a revision has a continuation-of header treeversion = None for l in output: rev = l.strip() self.changes[rev] = self.gnuarch_rev(rev) self.parents[rev] = [] # Read author, date and summary catlog, status = self.run(b'cat-log', b'-d', self.path, rev) if status: catlog = self.run0(b'cat-archive-log', rev) self._parsecatlog(catlog, rev) # Populate the parents map self.parents[child].append(rev) # Keep track of the current revision as the child of the next # revision scanned child = rev # Check if we have to follow the usual incremental history # or if we have to 'jump' to a different treeversion given # by the continuation-of header. if self.changes[rev].continuationof: treeversion = b'--'.join( self.changes[rev].continuationof.split(b'--')[:-1]) break # If we reached a base-0 revision w/o any continuation-of # header, it means the tree history ends here. if rev[-6:] == b'base-0': break
def __iter__(self): return (pycompat.fsencode(f.path) for f in self.git.index)