def rename(self, old, new): _old = old[1:] _new = new[1:] uid, gid, pid = fuse_get_context() username = pwd.getpwuid(uid)[0] dispatch(request(["--cwd", self.tmp, "mv", _old, _new])) dispatch( request( ["--cwd", self.tmp, "mv", os.path.join(".hgfs", _old + ".attr"), os.path.join(".hgfs", _new + ".attr")] ) ) dispatch( request( [ "--cwd", self.tmp, "commit", "-u", username, "-m", "hgfs[rename]: %s -> %s" % (_old, _new), str(_old), str(_new), ] ) ) if self.args.clone: dispatch(request(["--cwd", self.tmp, "push"])) return 0
def rmdir(self, path): _path = path[1:] apath = os.path.join(self.tmp, _path) dpath = os.path.join(self.tmp, ".hgfs", _path) hpath = os.path.join(self.tmp, ".hgfs", _path + ".attr") try: status = os.rmdir(dpath) except: pass status = os.rmdir(apath) try: status = os.unlink(hpath) except: pass uid, gid, pid = fuse_get_context() username = pwd.getpwuid(uid)[0] dispatch( request(["--cwd", self.tmp, "commit", "-A", "-u", username, "-m", "hgfs[rmdir]: %s" % (_path), str(_path)]) ) if self.args.clone: dispatch(request(["--cwd", self.tmp, "push"])) return status
def symlink(self, target, source): _source = source[1:] _target = target[1:] asource = os.path.join(self.tmp, _source) atarget = os.path.join(self.tmp, _target) status = os.symlink(source, atarget) uid, gid, pid = fuse_get_context() username = pwd.getpwuid(uid)[0] dispatch( request( [ "--cwd", self.tmp, "commit", "-A", "-u", username, "-m", "hgfs[symlink]: %s -> %s" % (_target, source), str(source), str(_target), ] ) ) if self.args.clone: dispatch(request(["--cwd", self.tmp, "push"])) return status
def destroy(self, path): try: dispatch(request(["--cwd", self.tmp, "commit", "-A", "-u", "hgfs", "-m", "hgfs[cruft]"])) if self.args.clone: dispatch(request(["--cwd", self.tmp, "push"])) finally: if self.args.clone: shutil.rmtree(self.tmp)
def handle(self, *args, **options): rebase = options.get('rebase', False) update = options.get('update', False) all = options.get('all', False) if rebase: pull_args = ['--rebase'] elif update: pull_args = ['-u'] else: pull_args = [] from life.models import Repository, Changeset from mercurial import dispatch import os.path from django.conf import settings def resolve(path): return os.path.join(settings.REPOSITORY_BASE, *path.split('/')) # check for last push helper file if not all and os.path.isfile(resolve('.latest_cs')): latest_cs = int(open(resolve('.latest_cs')).read()) repos = (Repository.objects .filter(changesets__id__gt=latest_cs) .distinct()) else: repos = Repository.objects.all() latest_cs = Changeset.objects.order_by('-pk')[0].id for name, url in repos.values_list('name', 'url'): repopath = str(resolve(name)) if not os.path.isdir(os.path.join(repopath, '.hg')): # new repo, need to clone if os.path.isdir(repopath): self.stdout.write(("\n\nCannot clone %s, " "existing directory in the way\n\n") % name) continue _parent = os.path.dirname(repopath) if not os.path.isdir(_parent): try: os.makedirs(_parent) except Exception as e: self.stdout.write( ("\n\nFailed to prepare for clone, %s\n\n" % str(e)) ) continue dispatch.dispatch( dispatch.request(['clone', str(url), repopath]) ) else: dispatch.dispatch( dispatch.request(['pull', '-R', repopath] + pull_args) ) open(resolve('.latest_cs'), 'w').write('%i\n' % latest_cs)
def handle(self, *args, **options): quiet = options.get('quiet', False) if not args: return try: ms = Milestone.objects.get(code=args[0]) except: raise CommandError, "No milestone with code %s found" % args[0] forest = ms.appver.tree.l10n.name.split('/') def resolve(path): return os.path.join(settings.REPOSITORY_BASE, *(forest + path.split('/'))) if ms.status == Milestone.SHIPPED: sos = ms.signoffs else: sos = accepted_signoffs(id=ms.appver_id) sos=dict(sos.values_list('locale__code', 'push_id')) tips = dict(Push.objects.filter(id__in=sos.values()).annotate(tip=Max('changesets__id')).values_list('id', 'tip')) revs = dict(Changeset.objects.filter(id__in=tips.values()).values_list('id','revision')) from mercurial import dispatch for loc in sorted(sos.keys()): repopath = resolve(loc) rev = revs[tips[sos[loc]]] dispatch.dispatch( dispatch.request(['update', '-R', repopath, '-r', rev]) )
def getattr(self, path, fh=None): if self.args.clone: dispatch(request(["--cwd", self.tmp, "pull", "-u"])) apath = os.path.join(self.tmp, path[1:]) st = os.lstat(apath) return dict((key, getattr(st, key)) for key in self.ATTRS)
def read(self, path, size, offset, fh): if self.args.clone: dispatch(request(["--cwd", self.tmp, "pull", "-u"])) os.lseek(fh, offset, os.SEEK_SET) data = os.read(fh, size) return data
def dispatch(ui, args): if hasattr(hgdispatch, 'request'): # hg >= 1.9, see mercurial changes 08bfec2ef031, 80c599eee3f3 req = hgdispatch.request(args, ui) return hgdispatch._dispatch(req) else: # hg <= 1.8 return hgdispatch._dispatch(ui, args)
def write(self, path, data, offset, fh): _path = path[1:] apath = os.path.join(self.tmp, _path) os.lseek(fh, offset, os.SEEK_SET) os.write(fh, data) uid, gid, pid = fuse_get_context() username = pwd.getpwuid(uid)[0] dispatch( request(["--cwd", self.tmp, "commit", "-A", "-u", username, "-m", "hgfs[write]: %s" % (_path), str(_path)]) ) if self.args.clone: dispatch(request(["--cwd", self.tmp, "push"])) return len(data)
def testdispatch(cmd): """Simple wrapper around dispatch.dispatch() Prints command and result value, but does not handle quoting. """ print "running: %s" % (cmd,) req = dispatch.request(cmd.split()) result = dispatch.dispatch(req) print "result: %r" % (result,)
def open(self, path, flags): if self.args.clone: dispatch(request(["--cwd", self.tmp, "pull", "-u"])) self.__load_attributes() _path = path[1:] apath = os.path.join(self.tmp, _path) return os.open(apath, flags)
def truncate(self, path, length, fh=None): _path = path[1:] apath = os.path.join(self.tmp, _path) if fh == None: with open(apath, "wb") as f: pass else: os.ftruncate(fh, length) uid, gid, pid = fuse_get_context() username = pwd.getpwuid(uid)[0] dispatch( request( ["--cwd", self.tmp, "commit", "-A", "-u", username, "-m", "hgfs[truncate]: %s" % (_path), str(_path)] ) ) if self.args.clone: dispatch(request(["--cwd", self.tmp, "push"]))
def readdir(self, path, fh): if self.args.clone: dispatch(request(["--cwd", self.tmp, "pull", "-u"])) apath = os.path.join(self.tmp, path[1:]) paths = os.listdir(apath) clean = [] for path in paths: if path != ".hg" and path != ".hgfs": clean.append(path) return [".", ".."] + clean
def _dispatch(self, args): # TODO: use hglib in order to avoid pollution of global space? origwd = os.getcwd() ui = uimod.ui() ui.setconfig('ui', 'strict', True) ui.fout = StringIO.StringIO() ui.ferr = StringIO.StringIO() req = dispatch.request(list(args), ui=ui) try: result = dispatch._dispatch(req) or 0 return result, ui.fout.getvalue(), ui.ferr.getvalue() finally: os.chdir(origwd)
def main(): user = sys.argv[1] conf = sys.argv[2] # get original ssh command orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?') try: cmdargv = shlex.split(orig_cmd) except ValueError as e: sys.stderr.write("Illegal command \"%s\": %s\n" % (orig_cmd, e)) sys.exit(1) if cmdargv[:2] != ['hg', '-R'] or cmdargv[3:] != ['serve', '--stdio']: sys.stderr.write("Illegal command \"%s\"\n" % orig_cmd) sys.exit(1) repo = cmdargv[2].replace(os.sep, '', 1) perm = get_permissions(repo, conf) if not len(perm): sys.stderr.write("Repository \"%s\" not found\n" % repo) sys.exit(1) if 'location' not in perm: sys.stderr.write("Repository \"%s\" has no location\n" % repo) sys.exit(1) path = os.path.normpath(os.path.join( os.getcwd(), os.path.expanduser(perm['location']) )) if (user not in perm) or (perm[user] not in ['read', 'write']): sys.stderr.write("Access denied to \"%s\"\n" % repo) sys.exit(1) cmd = ['-R', path, 'serve', '--stdio'] if perm[user] == 'read': cmd += [ '--config', 'hooks.prechangegroup.hg-ssh=python:__main__.reject_push', '--config', 'hooks.prepushkey.hg-ssh=python:__main__.reject_push' ] dispatch.dispatch(dispatch.request(cmd))
def get_data(self, args): """ Return the data generated from mercurial. """ fout = StringIO.StringIO() ferr = StringIO.StringIO() dispatch.dispatch(dispatch.request(args, None, None, None, fout, ferr)) fout_value = fout.getvalue() ferr_value = ferr.getvalue() fout.close() ferr.close() return {"fout": base64.b64encode(fout_value), "ferr": base64.b64encode(ferr_value)}
def __init__(self, repo, mountpoint=".", args={}): self.log.setLevel(args.log) self.log.debug("repo: %s mountpoint: %s args: %s", repo, mountpoint, repr(args)) self.repo = repo self.mountpoint = os.path.abspath(mountpoint) self.args = args if not self.args.clone: self.repo = os.path.abspath(repo) self.log.debug("SELF: repo: %s mountpoint: %s args: %s", self.repo, self.mountpoint, repr(self.args)) if self.args.clone: self.tmp = os.path.abspath(tempfile.mkdtemp(prefix="hgfs-")) dispatch(request(["clone", self.repo, self.tmp])) else: self.tmp = self.repo self.log.debug("Tmp: %s", self.tmp) self.__load_attributes()
sys.stderr.write('Illegal command "%s": %s\n' % (orig_cmd, e)) sys.exit(255) if cmdargv[:2] == ['hg', '-R'] and cmdargv[3:] == ['serve', '--stdio']: path = cmdargv[2] repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path))) if path in perms: cmd = ['-R', repo, 'serve', '--stdio'] if perms[path] == "read": cmd += [ '--config', 'hooks.prechangegroup.hg-ssh=python:__main__.rejectpush', '--config', 'hooks.prepushkey.hg-ssh=python:__main__.rejectpush' ] dispatch.dispatch(dispatch.request(cmd)) else: sys.stderr.write('Illegal repository "%s"\n' % repo) sys.exit(255) else: sys.stderr.write('Illegal command "%s"\n' % orig_cmd) sys.exit(255) def rejectpush(ui, **kwargs): ui.warn("Permission denied\n") # mercurial hooks use unix process conventions for hook return values # so a truthy return means failure return True if __name__ == '__main__': main()
def hg_dispatch(cmdargv): logger.debug(_("Using in-process Mercurial dispatch")) return dispatch.dispatch(dispatch.request(cmdargv))
def lock(ui, repo, *pats, **opts): """ HGLock-LE is the extansion implements file locking funcionality that is vary similar to rcs(1). Usage: $ hg lock [-v] <file ...> If no file specified, the list of already locked files and lock owners will displayed. -v Will display a bit more information then usual. Other options are available only for hook execution handling. """ lockFile = repo.root + pathSep + ".hg" + pathSep + "locked.files" user = ui.username() ui.note("repository: %s\n" % repo.root) ui.note("lockfile: %s\n" % lockFile) ui.note("user name: %s\n\n" % user) # Identify whether function is called as a hook, # and if so, change the command and reexecute it. if 'hooktype' in opts: if opts['result'] == 0: cmdline = list() cmdline = opts['args'].split() cmdline[0] = 'lock' # remove dir names and symlinks for file in cmdline[::-1]: if os.path.isdir(file) or os.path.islink(file): cmdline.remove(file) # Fixing problems around changed dispatcher (since v1.9) if hasattr(dispatch, 'request'): return(dispatch.dispatch(dispatch.request(cmdline))) else: return(dispatch.dispatch(cmdline)) else: return(opts['result']) # Calculate file path in repository filesList=list() err=0 for file in pats: file = PathInRepo(repo.root, file) if file in repo.dirstate: filesList.append(file) else: ui.warn("%s\n" % (file)) err += 1 if err: raise util.Abort(i18n._("cant't lock untracked file(s).")) # Load stored locking data lockedFilesList = LoadData(lockFile) # Show available locks if "filesList" is empty if not filesList: for file in lockedFilesList.keys(): if ui.verbose: ui.write("%s is locked by %s (%s)\n" % \ (file, lockedFilesList[file][UserName], lockedFilesList[file][LockDate])) else: ui.write("%s (%s)\n" % (file, lockedFilesList[file][UserName])) return 0 # Collect locked files if available alreadyLocked = list() for file in filesList: if file in lockedFilesList: alreadyLocked.append(file) if not alreadyLocked: # Locking for file in filesList: localTime = datetime.datetime.now() localTime = localTime.ctime() lockedFilesList[file] = (user,localTime) ui.note("locking: %s\n" % file) #ui.write ("%s is locked.\n" % (file)) StoreData(lockFile, lockedFilesList) else: # Exit with errno for file in alreadyLocked: if ui.verbose: ui.write("%s - is already locked by %s (%s)\n" % \ (file,lockedFilesList[file][UserName],lockedFilesList[file][LockDate])) else: ui.write("%s (%s)\n" % \ (file,lockedFilesList[file][UserName])) raise util.Abort(i18n._("lock(s) conflict."))
def unlock(ui, repo, *pats, **opts): """ Release Lock: $ hg unlock [-f] [-v] <file ...> If no file specified, unlock would try to relaes all availble locks. -f Force unlock. Allows you to break others locks. Owner will be notified about this. -v Will display a bit more information then usual. Other options are available only for hook execution handling. """ lockFile = repo.root + pathSep + ".hg" + pathSep + "locked.files" user = ui.username() ui.note("repository: %s\n" % repo.root) ui.note("lockfile: %s\n" % lockFile) ui.note("user name: %s\n\n" % user) filesList=list() # Identify whether function is called as a hook, # and if so, change the command and reexecutei it. if 'hooktype' in opts: cmdline = list() cmdline = opts['args'].split() cmdline[0] = 'unlock' # Fixing problems around changed dispatcher (since v1.9) if hasattr(dispatch, 'request'): return(dispatch.dispatch(dispatch.request(cmdline))) else: return(dispatch.dispatch(cmdline)) #Calculate file path in repository if pats: for file in pats: if not os.path.exists(file): # file defined as path in repo (via hook call) if file in repo.dirstate: filesList.append(file) else: filesList.append(PathInRepo(repo.root, file)) # Load stored locking data lockedFilesList = LoadData(lockFile) # If files are not specified # try to release all available locks if not pats: filesList = lockedFilesList.keys() err = 0 for file in filesList: ui.note("checking: %s\n" % file) if file in lockedFilesList: # UnLock if not lockedFilesList[file][UserName] == user: # Force unlock and send email to lock owner if opts['force']: # Email format: RFC 2822 # example: "Vladimir Legeza <*****@*****.**>" from mercurial import mail sendFrom = util.email(user) sendTo = [util.email(lockedFilesList[file][UserName])] message = "The lock you have set on '%s' file was removed by %s." % \ (file, lockedFilesList[file][UserName]) ui.note("sending email to: %s\n" % sendTo) mail.sendmail(ui, sendFrom, sendTo, message) ui.note("unlocking: %s\n" % file) lockedFilesList.pop(file) else: err += 1 ui.warn("%s - locked by %s.\n" % (file, lockedFilesList[file][UserName])) else: ui.note("unlocking: %s\n" % file) lockedFilesList.pop(file) if err: raise util.Abort(i18n._("Lock ownership violation.")) # Save changes StoreData(lockFile, lockedFilesList)
def readlink(self, path): if self.args.clone: dispatch(request(["--cwd", self.tmp, "pull", "-u"])) apath = os.path.join(self.tmp, path[1:]) return os.readlink(apath)
def freenetclone(orig, *args, **opts): def parsepushargs(ui, repo, path=None): return ui, repo, path def isfreenetpath(path): try: if path.startswith("freenet:") or path.startswith("USK@"): return True except AttributeError: return False return False ui, source, dest = parsepushargs(*args) # only act differently, if dest or source is an infocalypse repo. if not isfreenetpath(source) and not isfreenetpath(dest): return orig(*args, **opts) if not dest: if not isfreenetpath(source): dest = hg.defaultdest(source) else: # this is a freenet key. It has a /# at the end and # could contain .R1 or .R0 as pure technical identifiers # which we do not need in the local name. segments = source.split("/") pathindex = -2 try: int(segments[-1]) except ValueError: # no number revision pathindex = -1 dest = segments[pathindex] if dest.endswith(".R1") or dest.endswith(".R0"): dest = dest[:-3] # TODO: source holds the "repo" argument, but the naming is confusing in # the context of freenetpathtouri(). # check whether to create, pull or copy pulluri, pushuri = None, None if isfreenetpath(source): pulluri = parse_repo_path( freenetpathtouri(ui, source, "pull", None, opts.get('truster'))) if isfreenetpath(dest): pushuri = parse_repo_path(freenetpathtouri(ui, dest, "clone-push", fcphost = opts['fcphost'], fcpport = opts['fcpport']), assume_redundancy=True) # decide which infocalypse command to use. if pulluri and pushuri: action = "copy" elif pulluri: action = "pull" elif pushuri: action = "create" else: raise util.Abort("""Can't clone without source and target. This message should not be reached. If you see it, this is a bug.""") if action == "copy": raise util.Abort("""Cloning without intermediate local repo not yet supported in the simplified commands. Use fn-copy directly.""") if action == "create": # if the pushuri is the short form (USK@/name/#), generate the key. if pushuri.startswith("USK@/"): ui.status("creating a new key for the repo. To use your default key, call fn-create.\n") from sitecmds import genkeypair fcphost, fcpport = opts["fcphost"], opts["fcpport"] if not fcphost: fcphost = DEFAULT_FCP_HOST if not fcpport: fcpport = DEFAULT_FCP_PORT # use redundant keys by default, except if explicitely requested otherwise. namepart = pushuri[5:] namepart = fixnamepart(namepart) insert, request = genkeypair(fcphost, fcpport) pushuri = "USK"+insert[3:]+namepart elif pushuri.endswith("/0"): # initial create, catch the no-.R1 error pass # this rewriting is dangerous here since it could make it # impossible to update old repos when they drop # out. Leaving it commented out for now. TODO: Always # treat a name without .R0 as requesting redundancy *in. # the backend*. Keep it as /name/#, but add /name.Rn/0 # backup repos. Needs going into the backend. #namepart = pushuri.split("/")[-2] + "/0" #namepartpos = -len(namepart) #namepart2 = fixnamepart(namepart) # if namepart2 != namepart: # ui.status("changed the repo name to " + namepart2 + " to have more redundancy and longer lifetime. This is a small tweak on infocalypse to avoid the frequent error of forgetting to add .R1 to the name. If you really want no additional redundancy for your repo, use NAME.R0 or call hg fn-create directly.\n") #pushuri = pushuri[:namepartpos] + namepart opts["uri"] = pushuri repo = hg.repository(ui, ui.expandpath(source)) # TODO: A local identity is looked up for the push URI, # but not returned, yet it is required to update configuration. # Expecting dest to be something like freenet://name@key/reponame local_identifier = strip_protocol(dest).split('/')[0] from wot_id import Local_WoT_ID from wot import get_fcpopts local_identity = Local_WoT_ID(local_identifier, get_fcpopts(fcphost=opts["fcphost"], fcpport=opts["fcpport"])) infocalypse_create(ui, repo, local_identity, **opts) # TODO: Function for adding paths? It's currently here, for pull, # and in WoT pull URI resolution. with repo.opener("hgrc", "a", text=True) as f: f.write("""[paths] default-push = freenet:{0} """.format(pushuri)) if action == "pull": if os.path.exists(dest): raise util.Abort(_("destination " + dest + " already exists.")) # create the repo req = dispatch.request(["init", dest], ui=ui) dispatch.dispatch(req) # pull the data from freenet origdest = ui.expandpath(dest) dest, branch = hg.parseurl(origdest) destrepo = hg.repository(ui, dest) infocalypse_pull(ui, destrepo, aggressive=True, hash=None, uri=pulluri, **opts) # store the request uri for future updates _hgrc_template = """[paths] default = freenet://{pulluri} [ui] username = anonymous [alias] clt = commit ci = !$HG clt --date "$(date -u "+%Y-%m-%d %H:%M:%S +0000")" "$@" commit = !$HG clt --date "$(date -u "+%Y-%m-%d %H:%M:%S +0000")" "$@" """ # alternative: every commit is done at 09:42:30 (might be # confusing but should be safest): date -u "+%Y-%m-%d 09:42:30 +0000 # second alternative: commit done at local time but with # timezone +0000 (could be correlated against forum entries # and such to find the real timezone): Leave out the -u with destrepo.opener("hgrc", "a", text=True) as f: f.write(_hgrc_template.format(pulluri=pulluri)) ui.warn("As basic protection, infocalypse automatically \n" " set the username 'anonymous' for commits in this repo, \n" " changed the commands `commit` and `ci` to fake UTC time \n" " and added `clt` which commits in the local timezone. \n" " To change this, edit " + str(os.path.join(destrepo.root, ".hg", "hgrc")) + "\n") # and update the repo return hg.update(destrepo, None)
def dispatch(ui, args): req = hgdispatch.request(args, ui) return hgdispatch._dispatch(req)
def main(): cwd = os.getcwd() user = sys.argv[1] conf = sys.argv[2] # Get the original SSH Command sent through. The repo should be the item after the connect string orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?') try: cmdargv = shlex.split(orig_cmd) # Changed to "as" here for Python 3.3 compatibility except ValueError as e: sys.stderr.write('Illegal command "%s": %s\n' % (orig_cmd, e)) sys.exit(255) if cmdargv[:2] == ['hg', '-R'] and cmdargv[3:] == ['serve', '--stdio']: try: # Now we need to extract the repository name (what is in the conf file) repository = cmdargv[2].replace(os.sep,'',1) # Get the repository and users from the config file (or get a blank {}) perms = get_permission(repository,conf) # If the returned dict is empty, then exit this process. This means no section with # the named repository exist! if not len(perms): sys.stderr.write('No repository found for "%s"\n' % repository) sys.exit(255) # This is the reason we are using a try in case this key does not exist. # 'location' param under repository section contains the relative or absolute path # to the repository on the file system from the current working # directory which can be changed in the authorized_keys path = perms['location'] # Get the path of the repository to be used with hg commands below. # This is the translation between the section name in the conf file and # the location param that points to the actual directory on the file system # By default, this uses cwd (Current working directory) and can be changed in the # authorized_keys file in the command section by using 'cd /path/to/start/from && ' # as the first part of the command string before calling this script. repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path))) except KeyError: sys.stderr.write('Invalid Repository "%s"\n' % repository) sys.exit(255) # We will try and get the username out of the config, if it is not present, we exit! # We will also check to make sure the access is set to read or write. If Not, goodbye! try: access = perms[user] except: sys.stderr.write('Illegal Repository "%s"\n' % repo) sys.exit(255) # If the user does not have read or write (write implies read) we exit. if access not in ['read','write']: sys.stderr.write('Access denied to "%s"\n' % repository) sys.exit(255) cmd = ['-R', repo, 'serve', '--stdio'] if access == "read": cmd += [ '--config', 'hooks.prechangegroup.hg-ssh=python:__main__.rejectpush', '--config', 'hooks.prepushkey.hg-ssh=python:__main__.rejectpush' ] dispatch.dispatch(dispatch.request(cmd)) else: sys.stderr.write('Illegal command "%s"\n' % orig_cmd) sys.exit(255)
apath = os.path.join(self.tmp, _path) st = os.stat(apath) attributes = dict((key, getattr(st, key)) for key in self.ATTRS) uid, gid, pid = fuse_get_context() username = pwd.getpwuid(uid)[0] attributes[".hgfs"] = {"pw_uid": uid, "pw_name": username, "gr_gid": gid, "gr_name": grp.getgrgid(gid)[0]} modpath = os.path.join(self.tmp, ".hgfs", _path + ".attr") with open(modpath, "wb+") as f: f.write(json.dumps(attributes, sort_keys=True, indent=2)) ahgfs = os.path.join(self.tmp, ".hgfs") dispatch(request(["--cwd", self.tmp, "commit", "-A", "-u", username, "-m", msg, ".hgfs", str(_path)])) if self.args.clone: dispatch(request(["--cwd", self.tmp, "push"])) def access(self, path, mode): _path = path[1:] apath = os.path.join(self.tmp, _path) if not os.access(apath, mode): raise FuseOSError(EACCES) def chmod(self, path, mode): _path = path[1:] apath = os.path.join(self.tmp, _path) status = os.chmod(apath, mode)
def dispatch(*args): return _dispatch.dispatch(_dispatch.request(*args))
def runcmd(): dispatch.dispatch(dispatch.request(['version', '-q'], ui_))
def _dispatch(ui, cmd): try: req = dispatch.request(cmd, ui=ui) dispatch._dispatch(req) except AttributeError: dispatch._dispatch(ui, cmd)