def commitcommand(orig, ui, repo, *args, **kwargs): pr_url = kwargs.get('manualservosync') if not pr_url: return orig(ui, repo, *args, **kwargs) m = GITHUB_PR_URL.match(pr_url) if m is None: raise error.Abort( _('--manualservosync was not a proper github pull request url'), hint=_('url must be to a servo/servo pull request of the form ' 'https://github.com/servo/servo/pull/<pr-number>')) pr = m.group('pr') revset = urllib.quote('keyword("servo: Merge #%s")' % pr) url = '%s/json-log?rev=%s' % (LINEAR_REPO_URL, revset) r = requests.get(url) commits = r.json()['entries'] if not commits: raise error.Abort( _('could not find linearized commit corresponding to %s' % pr_url), hint=_('If this pull requests has recently been merged it ' 'may not be linearized yet, please try again soon')) repo.manualsync_commit = { 'desc': encoding.tolocal(commits[0]['desc'].encode('utf-8')), 'node': encoding.tolocal(commits[0]['node'].encode('utf-8')), 'user': encoding.tolocal(commits[0]['user'].encode('utf-8')), } repo.manualsync_pr = pr repo.manualsync = True return orig(ui, repo, *args, **kwargs)
def localbranches(self): branches = [] bdir = self.join('branches') if os.path.isdir(bdir): for d in os.listdir(bdir): branches.append(encoding.tolocal(store.decodefilename(d))) return branches
def read(repo): '''Parse .hg/bookmarks file and return a dictionary Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values in the .hg/bookmarks file. Read the file and return a (name=>nodeid) dictionary ''' bookmarks = {} try: for line in repo.opener('bookmarks'): line = line.strip() if not line: continue if ' ' not in line: repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n') % line) continue sha, refspec = line.split(' ', 1) refspec = encoding.tolocal(refspec) try: bookmarks[refspec] = repo.changelog.lookup(sha) except error.RepoLookupError: pass except IOError, inst: if inst.errno != errno.ENOENT: raise
def testlossy0xed(self): encoding.encoding = b'euc-kr' # U+Dxxx Hangul s = u'\ud1bc\xc0'.encode('utf-8') l = encoding.tolocal(s) self.assertIn(b'\xed', l) self.assertTrue(l.endswith(b'?')) # lossy self.assertEqual(s, encoding.toutf8b(l)) # utf8 sequence preserved
def remotelookup(orig, repo, proto, key): k = encoding.tolocal(key) if k.startswith('_gitlookup_'): ret = _dolookup(repo, k) if ret is not None: success = 1 return '%s %s\n' % (success, ret) return orig(repo, proto, key)
def rewrite_commit_descriptions(ui, repo, node, descriptions=None): if not node: node = 'tip' ctx = repo[node] nodes = [ctx.node()] for ancestor in ctx.ancestors(): ctx = repo[ancestor] if ctx.phase() != phases.draft: break nodes.append(ctx.node()) nodes.reverse() description_map = {} with open(descriptions, 'rb') as f: raw_descriptions = json.load(f) for k in raw_descriptions: description_map[k] = encoding.tolocal(raw_descriptions[k].encode('utf-8')) def prune_unchanged(node): sha1 = repo[node].hex()[:12] description = repo[node].description() revised_description = description_map.get(sha1, description) if description == revised_description: ui.write(_('not rewriting %s - description unchanged\n' % sha1)) return False return True nodes = filter(prune_unchanged, nodes) if not nodes: ui.write(_('no commits found to be rewritten\n')) return 1 def createfn(repo, ctx, revmap, filectxfn): parents = rewrite.newparents(repo, ctx, revmap) sha1 = ctx.hex()[:12] if sha1 in description_map: description = description_map[sha1] else: description = ctx.description() memctx = context.memctx(repo, parents, description, ctx.files(), filectxfn, user=ctx.user(), date=ctx.date(), extra=ctx.extra()) status = ctx.p1().status(ctx) memctx.modified = lambda: status[0] memctx.added = lambda: status[1] memctx.removed = lambda: status[2] return memctx rewrite.replacechangesets(repo, nodes, createfn)
def makememctx(repo, ctx, revmap, copyfilectxfn): parents = newparents(repo, ctx, revmap) # Need to make a copy otherwise modification is made on original, # which is just plain wrong. msg = encoding.fromlocal(ctx.description()) new_msg, changed = addcommitid(msg, repo=repo) memctx = context.memctx(repo, parents, encoding.tolocal(new_msg), ctx.files(), copyfilectxfn, user=ctx.user(), date=ctx.date(), extra=dict(ctx.extra())) return memctx
def geturl(path): try: return svn.client.url_from_path(svn.core.svn_path_canonicalize(path)) except SubversionException: pass if os.path.isdir(path): path = os.path.normpath(os.path.abspath(path)) if os.name == 'nt': path = '/' + util.normpath(path) # Module URL is later compared with the repository URL returned # by svn API, which is UTF-8. path = encoding.tolocal(path) return 'file://%s' % urllib.quote(path) return path
def readcurrent(repo): '''Get the current bookmark If we use gittishsh branches we have a current bookmark that we are on. This function returns the name of the bookmark. It is stored in .hg/bookmarks.current ''' mark = None if os.path.exists(repo.join('bookmarks.current')): file = repo.opener('bookmarks.current') # No readline() in posixfile_nt, reading everything is cheap mark = encoding.tolocal((file.readlines() or [''])[0]) if mark == '': mark = None file.close() return mark
def read(repo): '''Parse .hg/bookmarks file and return a dictionary Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values in the .hg/bookmarks file. Read the file and return a (name=>nodeid) dictionary ''' try: bookmarks = {} for line in repo.opener('bookmarks'): sha, refspec = line.strip().split(' ', 1) refspec = encoding.tolocal(refspec) bookmarks[refspec] = repo.changelog.lookup(sha) except: pass return bookmarks
def _lookup(repo, proto, key): localkey = encoding.tolocal(key) if isinstance(localkey, str) and _scratchbranchmatcher(localkey): scratchnode = repo.bundlestore.index.getnode(localkey) if scratchnode: return "%d %s\n" % (1, scratchnode) else: return "%d %s\n" % (0, 'scratch branch %s not found' % localkey) else: try: r = hex(repo.lookup(localkey)) return "%d %s\n" % (1, r) except Exception as inst: if repo.bundlestore.index.getbundle(localkey): return "%d %s\n" % (1, localkey) else: r = stringutil.forcebytestr(inst) return "%d %s\n" % (0, r)
def commit(self, *args, **kwargs): if not self.manualsync: return super(servosyncrepo, self).commit(*args, **kwargs) kwargs = pycompat.byteskwargs(kwargs) # Override some of the commit meta data. msg = self.manualsync_commit[b'desc'] user = self.manualsync_commit[b'user'] # This method has many keyword arguments that mercurial # ocassionally passes positionally, meanig they end up # in *args, instead of **kwargs. This can be problematic as # naively modifying the value in **kwargs will result in # the argument being passed twice, which is an error. # Protect against this by stripping the values out of # *args and **kwargs, passing them positionally ourselves. for key in (b'text', b'user'): if args: args = args[1:] if key in kwargs: del kwargs[key] kwargs[b'extra'] = kwargs[b'extra'] if b'extra' in kwargs else {} kwargs[b'extra'][SOURCE_KEY] = encoding.tolocal(LINEAR_REPO_URL) kwargs[b'extra'][REVISION_KEY] = self.manualsync_commit[b'node'] # TODO: Verify that the file changes being committed are only # under the servo/ directory. ret = super(servosyncrepo, self).commit(msg, user, *args, **pycompat.strkwargs(kwargs)) ctx = repo[ret] if any(not f.startswith(b'servo/') for f in ctx.files()): self.ui.warn( _(b'warning: this commit touches files outside the servo ' b'directory and would be rejected by the server\n')) return ctx
def __init__(self, repo): dict.__init__(self) self._repo = repo try: for line in repo.vfs('remoterefs'): line = line.strip() if not line: continue sha, ref = line.split(None, 1) ref = encoding.tolocal(ref) try: self[ref] = repo.changelog.lookup(sha) except LookupError: pass except IOError as e: if e.errno != errno.ENOENT: raise
def __init__(self, repo): dict.__init__(self) self._repo = repo try: bkfile = self.getbkfile(repo) for line in bkfile: line = line.strip() if not line: continue if " " not in line: repo.ui.warn(_("malformed line in .hg/bookmarks: %r\n") % line) continue sha, refspec = line.split(" ", 1) refspec = encoding.tolocal(refspec) try: self[refspec] = repo.changelog.lookup(sha) except LookupError: pass except IOError, inst: if inst.errno != errno.ENOENT: raise
def manifest(self): # As of svn 1.7, the "add" command fails when receiving # already tracked entries, so we have to track and filter them # ourselves. m = set() output = self.run0('ls', recursive=True, xml=True) doc = xml.dom.minidom.parseString(output) for e in doc.getElementsByTagName('entry'): for n in e.childNodes: if n.nodeType != n.ELEMENT_NODE or n.tagName != 'name': continue name = ''.join(c.data for c in n.childNodes if c.nodeType == c.TEXT_NODE) # Entries are compared with names coming from # mercurial, so bytes with undefined encoding. Our # best bet is to assume they are in local # encoding. They will be passed to command line calls # later anyway, so they better be. m.add(encoding.tolocal(name.encode('utf-8'))) break return m
def readactive(repo): """ Get the active bookmark. We can have an active bookmark that updates itself as we commit. This function returns the name of that bookmark. It is stored in .hg/bookmarks.current """ mark = None try: file = repo.vfs('bookmarks.current') except IOError as inst: if inst.errno != errno.ENOENT: raise return None try: # No readline() in osutil.posixfile, reading everything is cheap mark = encoding.tolocal((file.readlines() or [''])[0]) if mark == '' or mark not in repo._bookmarks: mark = None finally: file.close() return mark
def __init__(self, repo): dict.__init__(self) self._repo = repo try: for line in repo.vfs('bookmarks'): line = line.strip() if not line: continue if ' ' not in line: repo.ui.warn( _('malformed line in .hg/bookmarks: %r\n') % line) continue sha, refspec = line.split(' ', 1) refspec = encoding.tolocal(refspec) try: self[refspec] = repo.changelog.lookup(sha) except LookupError: pass except IOError, inst: if inst.errno != errno.ENOENT: raise
def __init__(self, repo): dict.__init__(self) self._repo = repo try: for line in repo.vfs('bookmarks'): line = line.strip() if not line: continue if ' ' not in line: repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n') % line) continue sha, refspec = line.split(' ', 1) refspec = encoding.tolocal(refspec) try: self[refspec] = repo.changelog.lookup(sha) except LookupError: pass except IOError, inst: if inst.errno != errno.ENOENT: raise
def pygmentize(field, fctx, style, tmpl): # append a <link ...> to the syntax highlighting css old_header = ''.join(tmpl('header')) if SYNTAX_CSS not in old_header: new_header = old_header + SYNTAX_CSS tmpl.cache['header'] = new_header text = fctx.data() if util.binary(text): return # avoid UnicodeDecodeError in pygments text = encoding.tolocal(text) # To get multi-line strings right, we can't format line-by-line try: lexer = guess_lexer_for_filename(fctx.path(), text[:1024], encoding=encoding.encoding) except (ClassNotFound, ValueError): try: lexer = guess_lexer(text[:1024], encoding=encoding.encoding) except (ClassNotFound, ValueError): lexer = TextLexer(encoding=encoding.encoding) formatter = HtmlFormatter(style=style, encoding=encoding.encoding) colorized = highlight(text, lexer, formatter) # strip wrapping div colorized = colorized[:colorized.find('\n</pre>')] colorized = colorized[colorized.find('<pre>') + 5:] coloriter = iter(colorized.splitlines()) tmpl.filters['colorize'] = lambda x: coloriter.next() oldl = tmpl.cache[field] newl = oldl.replace('line|escape', 'line|colorize') tmpl.cache[field] = newl
def pygmentize(field, fctx, style, tmpl): # append a <link ...> to the syntax highlighting css old_header = ''.join(tmpl('header')) if SYNTAX_CSS not in old_header: new_header = old_header + SYNTAX_CSS tmpl.cache['header'] = new_header text = fctx.data() if util.binary(text): return # avoid UnicodeDecodeError in pygments text = encoding.tolocal(text) # To get multi-line strings right, we can't format line-by-line try: lexer = guess_lexer_for_filename(fctx.path(), text[:1024], encoding=encoding.encoding) except (ClassNotFound, ValueError): try: lexer = guess_lexer(text[:1024], encoding=encoding.encoding) except (ClassNotFound, ValueError): lexer = TextLexer(encoding=encoding.encoding) formatter = HtmlFormatter(style=style, encoding=encoding.encoding) colorized = highlight(text, lexer, formatter) # strip wrapping div colorized = colorized[:colorized.find('\n</pre>')] colorized = colorized[colorized.find('<pre>')+5:] coloriter = iter(colorized.splitlines()) tmpl.filters['colorize'] = lambda x: coloriter.next() oldl = tmpl.cache[field] newl = oldl.replace('line|escape', 'line|colorize') tmpl.cache[field] = newl
def u2hg(s): """Returns a mercurial string representing an unicode object.""" return encoding.tolocal(s.encode("utf-8"))
u = ui.ui() repo = hg.repository(u, 'test1', create=1) os.chdir('test1') # create 'foo' with fixed time stamp f = open('foo', 'w') f.write('foo\n') f.close() os.utime('foo', (1000, 1000)) # add+commit 'foo' repo[None].add(['foo']) repo.commit(text='commit1', date="0 0") print "workingfilectx.date =", repo[None]['foo'].date() # test memctx with non-ASCII commit message def filectxfn(repo, memctx, path): return context.memfilectx("foo", "") ctx = context.memctx(repo, ['tip', None], encoding.tolocal("Gr\xc3\xbcezi!"), ["foo"], filectxfn) ctx.commit() for enc in "ASCII", "Latin-1", "UTF-8": encoding.encoding = enc print "%-8s: %s" % (enc, repo["tip"].description())
def branch(self): return encoding.tolocal(self._changeset.extra.get("branch"))
'''Get the current bookmark If we use gittish branches we have a current bookmark that we are on. This function returns the name of the bookmark. It is stored in .hg/bookmarks.current ''' mark = None try: file = repo.vfs('bookmarks.current') except IOError, inst: if inst.errno != errno.ENOENT: raise return None try: # No readline() in osutil.posixfile, reading everything is cheap mark = encoding.tolocal((file.readlines() or [''])[0]) if mark == '' or mark not in repo._bookmarks: mark = None finally: file.close() return mark def setcurrent(repo, mark): '''Set the name of the bookmark that we are currently on Set the name of the bookmark that we are on (hg update <bookmark>). The name is recorded in .hg/bookmarks.current ''' if mark not in repo._bookmarks: raise AssertionError('bookmark %s does not exist!' % mark)
def appendValue(doc, node, value): textNode = doc.createTextNode(encoding.tolocal(value)) node.appendChild(textNode)
def testasciifastpath(self): s = b'\0' * 100 self.assertTrue(s is encoding.tolocal(s)) self.assertTrue(s is encoding.fromlocal(s))
def getlocalbranch(self): try: branch = repo.opener('localbranch').read().rstrip('\n') except IOError: branch = '' return encoding.tolocal(branch)
def rewrite_commit_descriptions(ui, repo, base_node, descriptions=None): def sha1_of(node): return repo[node].hex()[:12] # Rewriting fails if the evolve extension is enabled. try: extensions.find('evolve') raise error.Abort('Cannot continue as the "evolve" extension is ' 'enabled.') except KeyError: pass # Read commit descriptions map. description_map = {} with open(descriptions, 'rb') as f: raw_descriptions = json.load(f) for sha1 in raw_descriptions: description_map[sha1[:12]] = encoding.tolocal( raw_descriptions[sha1].encode('utf-8')) # Collect nodes listed by description_map. nodes = [] def add_node(ctx): node = ctx.node() if sha1_of(node) in description_map: nodes.append(node) ctx = repo[base_node] add_node(ctx) for ancestor in ctx.ancestors(): if ctx.phase() != phases.draft: break add_node(repo[ancestor]) nodes.reverse() if not nodes: raise error.Abort('No commits found to be rewritten.') # We need to store the original sha1 values because we won't be able to # look them up once they are rewritten. original_sha1s = {} for node in nodes: original_sha1s[node] = sha1_of(node) # Update changed nodes. def prune_unchanged(node): return repo[node].description() != description_map[sha1_of(node)] def create_func(repo, ctx, revmap, filectxfn): parents = rewrite.newparents(repo, ctx, revmap) sha1 = ctx.hex()[:12] description = description_map[sha1] memctx = context.memctx(repo, parents, description, ctx.files(), filectxfn, user=ctx.user(), date=ctx.date(), extra=ctx.extra()) status = ctx.p1().status(ctx) memctx.modified = lambda: status[0] memctx.added = lambda: status[1] memctx.removed = lambda: status[2] return memctx node_map = {} changed_nodes = filter(prune_unchanged, nodes) if changed_nodes: node_map = rewrite.replacechangesets(repo, changed_nodes, create_func) # Output result. for node in nodes: original_sha1 = original_sha1s[node] if node in node_map: new_sha1 = sha1_of(node_map[node]) else: new_sha1 = original_sha1s[node] ui.write('rev: %s -> %s\n' % (original_sha1, new_sha1))
def wireprotolistkeyspatterns(repo, proto, namespace, patterns): patterns = wireprototypes.decodelist(patterns) d = repo.listkeys(encoding.tolocal(namespace), patterns).iteritems() return pushkey.encodekeys(d)
repo[None].add([b'foo']) repo.commit(text=b'commit1', date=b"0 0") d = repo[None][b'foo'].date() if os.name == 'nt': d = d[:2] print("workingfilectx.date = (%d, %d)" % d) # test memctx with non-ASCII commit message def filectxfn(repo, memctx, path): return context.memfilectx(repo, memctx, b"foo", b"") ctx = context.memctx(repo, [b'tip', None], encoding.tolocal(b"Gr\xc3\xbcezi!"), [b"foo"], filectxfn) ctx.commit() for enc in "ASCII", "Latin-1", "UTF-8": encoding.encoding = enc printb(b"%-8s: %s" % (enc.encode('ascii'), repo[b"tip"].description())) # test performing a status def getfilectx(repo, memctx, f): fctx = memctx.parents()[0][f] data, flags = fctx.data(), fctx.flags() if f == b'foo': data += b'bar\n' return context.memfilectx(repo, memctx, f, data, b'l' in flags, b'x'
def testlossless0xed(self): encoding.encoding = b'euc-kr' # U+Dxxx Hangul s = u'\ud1bc'.encode('utf-8') l = encoding.tolocal(s) self.assertEqual(l, b'\xc5\xed') # lossless self.assertEqual(s, encoding.toutf8b(l)) # convert back to utf-8
def rewrite_commit_descriptions(ui, repo, base_node, descriptions=None): def sha1_short(node): return repo[node].hex()[:12] def sha1_full(node): return repo[node].hex() # Rewriting fails if the evolve extension is enabled. try: extensions.find("evolve") raise error.Abort('Cannot continue as the "evolve" extension is ' "enabled.") except KeyError: pass # Read commit descriptions map. # MozReview passes in short SHA1 (12 chars), so we have to use [:12] here # and in `add_node`. description_map = {} with open(descriptions, "rb") as f: raw_descriptions = json.load(f) for sha1 in raw_descriptions: description_map[sha1[:12]] = encoding.tolocal( raw_descriptions[sha1].encode("utf-8")) # Collect nodes listed by description_map. nodes = [] def add_node(ctx): node = ctx.node() if sha1_short(node) in description_map: nodes.append(node) ctx = repo[base_node] add_node(ctx) for ancestor in ctx.ancestors(): if ctx.phase() != phases.draft: break add_node(repo[ancestor]) nodes.reverse() if not nodes: raise error.Abort("No commits found to be rewritten.") # We need to store the original sha1 values because we won't be able to # look them up once they are rewritten. original_sha1s = {} for node in nodes: original_sha1s[node] = sha1_full(node) # Update changed nodes. def create_func(repo, ctx, revmap, filectxfn): parents = rewrite.newparents(repo, ctx, revmap) sha1 = ctx.hex()[:12] description = description_map[sha1] memctx = context.memctx( repo, parents, description, ctx.files(), filectxfn, user=ctx.user(), date=ctx.date(), extra=ctx.extra(), ) status = ctx.p1().status(ctx) memctx.modified = lambda: status[0] memctx.added = lambda: status[1] memctx.removed = lambda: status[2] return memctx node_map = rewrite.replacechangesets(repo, nodes, create_func) # Output result. for node in nodes: ui.write("rev: %s -> %s\n" % (original_sha1s[node], sha1_full(node_map[node])))
def testlossylatin(self): encoding.encoding = b'ascii' s = u'\xc0'.encode('utf-8') l = encoding.tolocal(s) self.assertEqual(l, b'?') # lossy self.assertEqual(s, encoding.toutf8b(l)) # utf8 sequence preserved
'''Get the current bookmark If we use gittishsh branches we have a current bookmark that we are on. This function returns the name of the bookmark. It is stored in .hg/bookmarks.current ''' mark = None try: file = repo.opener('bookmarks.current') except IOError, inst: if inst.errno != errno.ENOENT: raise return None try: # No readline() in posixfile_nt, reading everything is cheap mark = encoding.tolocal((file.readlines() or [''])[0]) if mark == '' or mark not in repo._bookmarks: mark = None finally: file.close() return mark def write(repo): '''Write bookmarks Write the given bookmark => hash dictionary to the .hg/bookmarks file in a format equal to those of localtags. We also store a backup of the previous state in undo.bookmarks that can be copied back on rollback. '''
def testlosslesslatin(self): encoding.encoding = b'latin-1' s = u'\xc0'.encode('utf-8') l = encoding.tolocal(s) self.assertEqual(l, b'\xc0') # lossless self.assertEqual(s, encoding.toutf8b(l)) # convert back to utf-8