Beispiel #1
0
def get_filelogs_at_cl(client, clnum):
    cmd = 'p4 --client %s -G fstat -T ' \
         '"depotFile,headAction,headType,headRev" ' \
         '"//%s/..."@%d' % (
         util.shellquote(client),
         util.shellquote(client),
         clnum
         )
    stdout = util.popen(cmd, mode='rb')
    try:
        result = []
        for d in loaditer(stdout):
            if d.get('depotFile'):
                headaction = d['headAction']
                if headaction in ACTION_ARCHIVE or headaction in ACTION_DELETE:
                    continue
                depotfile = d['depotFile']
                filelog = {}
                filelog[clnum] = {
                    'action': d['headAction'],
                    'type': d['headType'],
                }
                result.append(P4Filelog(depotfile, filelog))
        return result
    except Exception:
        raise P4Exception(stdout)
Beispiel #2
0
def uisetup(ui):
    for cmd, path in ui.configitems('extdiff'):
        path = util.expandpath(path)
        if cmd.startswith('cmd.'):
            cmd = cmd[4:]
            if not path:
                path = util.findexe(cmd)
                if path is None:
                    path = filemerge.findexternaltool(ui, cmd) or cmd
            diffopts = ui.config('extdiff', 'opts.' + cmd, '')
            cmdline = util.shellquote(path)
            if diffopts:
                cmdline += ' ' + diffopts
        elif cmd.startswith('opts.'):
            continue
        else:
            if path:
                # case "cmd = path opts"
                cmdline = path
                diffopts = len(shlex.split(cmdline)) > 1
            else:
                # case "cmd ="
                path = util.findexe(cmd)
                if path is None:
                    path = filemerge.findexternaltool(ui, cmd) or cmd
                cmdline = util.shellquote(path)
                diffopts = False
        # look for diff arguments in [diff-tools] then [merge-tools]
        if not diffopts:
            args = ui.config('diff-tools', cmd+'.diffargs') or \
                   ui.config('merge-tools', cmd+'.diffargs')
            if args:
                cmdline += ' ' + args
        command(cmd, extdiffopts[:], _('hg %s [OPTION]... [FILE]...') % cmd,
                inferrepo=True)(savedcmd(path, cmdline))
    def filter(self, filter, node, changelog, patchfile):
        """arbitrarily rewrite changeset before applying it"""

        self.ui.status(_("filtering %s\n") % patchfile)
        user, date, msg = (changelog[1], changelog[2], changelog[4])
        fd, headerfile = tempfile.mkstemp(prefix="hg-transplant-")
        fp = os.fdopen(fd, "w")
        fp.write("# HG changeset patch\n")
        fp.write("# User %s\n" % user)
        fp.write("# Date %d %d\n" % date)
        fp.write(msg + "\n")
        fp.close()

        try:
            util.system(
                "%s %s %s" % (filter, util.shellquote(headerfile), util.shellquote(patchfile)),
                environ={"HGUSER": changelog[1], "HGREVISION": revlog.hex(node)},
                onerr=util.Abort,
                errprefix=_("filter failed"),
                out=self.ui.fout,
            )
            user, date, msg = self.parselog(file(headerfile))[1:4]
        finally:
            os.unlink(headerfile)

        return (user, date, msg)
Beispiel #4
0
def uisetup(ui):
    for cmd, path in ui.configitems('extdiff'):
        path = util.expandpath(path)
        if cmd.startswith('cmd.'):
            cmd = cmd[4:]
            if not path:
                path = util.findexe(cmd)
                if path is None:
                    path = filemerge.findexternaltool(ui, cmd) or cmd
            diffopts = ui.config('extdiff', 'opts.' + cmd, '')
            cmdline = util.shellquote(path)
            if diffopts:
                cmdline += ' ' + diffopts
        elif cmd.startswith('opts.'):
            continue
        else:
            if path:
                # case "cmd = path opts"
                cmdline = path
                diffopts = len(pycompat.shlexsplit(cmdline)) > 1
            else:
                # case "cmd ="
                path = util.findexe(cmd)
                if path is None:
                    path = filemerge.findexternaltool(ui, cmd) or cmd
                cmdline = util.shellquote(path)
                diffopts = False
        # look for diff arguments in [diff-tools] then [merge-tools]
        if not diffopts:
            args = ui.config('diff-tools', cmd+'.diffargs') or \
                   ui.config('merge-tools', cmd+'.diffargs')
            if args:
                cmdline += ' ' + args
        command(cmd, extdiffopts[:], _('hg %s [OPTION]... [FILE]...') % cmd,
                inferrepo=True)(savedcmd(path, cmdline))
Beispiel #5
0
    def filter(self, filter, node, changelog, patchfile):
        '''arbitrarily rewrite changeset before applying it'''

        self.ui.status(_('filtering %s\n') % patchfile)
        user, date, msg = (changelog[1], changelog[2], changelog[4])
        fd, headerfile = tempfile.mkstemp(prefix='hg-transplant-')
        fp = os.fdopen(fd, 'w')
        fp.write("# HG changeset patch\n")
        fp.write("# User %s\n" % user)
        fp.write("# Date %d %d\n" % date)
        fp.write(msg + '\n')
        fp.close()

        try:
            util.system('%s %s %s' % (filter, util.shellquote(headerfile),
                                   util.shellquote(patchfile)),
                        environ={'HGUSER': changelog[1],
                                 'HGREVISION': revlog.hex(node),
                                 },
                        onerr=util.Abort, errprefix=_('filter failed'),
                        out=self.ui.fout)
            user, date, msg = self.parselog(file(headerfile))[1:4]
        finally:
            os.unlink(headerfile)

        return (user, date, msg)
Beispiel #6
0
    def filter(self, filter, changelog, patchfile):
        '''arbitrarily rewrite changeset before applying it'''

        self.ui.status('filtering %s\n' % patchfile)
        user, date, msg = (changelog[1], changelog[2], changelog[4])

        fd, headerfile = tempfile.mkstemp(prefix='hg-transplant-')
        fp = os.fdopen(fd, 'w')
        fp.write("# HG changeset patch\n")
        fp.write("# User %s\n" % user)
        fp.write("# Date %d %d\n" % date)
        fp.write(changelog[4])
        fp.close()

        try:
            util.system('%s %s %s' % (filter, util.shellquote(headerfile),
                                      util.shellquote(patchfile)),
                        environ={'HGUSER': changelog[1]},
                        onerr=util.Abort,
                        errprefix=_('filter failed'))
            user, date, msg = self.parselog(file(headerfile))[1:4]
        finally:
            os.unlink(headerfile)

        return (user, date, msg)
Beispiel #7
0
    def filter(self, filter, node, changelog, patchfile):
        '''arbitrarily rewrite changeset before applying it'''

        self.ui.status(_('filtering %s\n') % patchfile)
        user, date, msg = (changelog[1], changelog[2], changelog[4])
        fd, headerfile = tempfile.mkstemp(prefix='hg-transplant-')
        fp = os.fdopen(fd, pycompat.sysstr('w'))
        fp.write("# HG changeset patch\n")
        fp.write("# User %s\n" % user)
        fp.write("# Date %d %d\n" % date)
        fp.write(msg + '\n')
        fp.close()

        try:
            self.ui.system('%s %s %s' % (filter, util.shellquote(headerfile),
                                         util.shellquote(patchfile)),
                           environ={
                               'HGUSER': changelog[1],
                               'HGREVISION': nodemod.hex(node),
                           },
                           onerr=error.Abort,
                           errprefix=_('filter failed'),
                           blockedtag='transplant_filter')
            user, date, msg = self.parselog(file(headerfile))[1:4]
        finally:
            os.unlink(headerfile)

        return (user, date, msg)
Beispiel #8
0
def createtask(ui, repo, defaultdesc):
    """FBONLY: create task for source control oncall"""
    prompt = '''Title: [hg rage] %s on %s by %s

Description:
%s

HG: Edit task title and description. Lines beginning with 'HG:' are removed."
HG: First line is the title followed by the description.
HG: Feel free to add relevant information.
''' % (repo.root, socket.gethostname(), encoding.environ.get('LOGNAME'),
       defaultdesc)

    text = re.sub("(?m)^HG:.*(\n|$)", "", ui.edit(prompt, ui.username()))
    lines = text.splitlines()
    title = re.sub("(?m)^Title:\s+", "", lines[0])
    desc = re.sub("(?m)^Description:\s+", "", '\n'.join(lines[1:]))
    tag = 'hg rage'
    oncall = 'source_control'
    taskid = shcmd(' '.join([
        'tasks',
        'create',
        '--title=' + util.shellquote(title),
        '--pri=low',
        '--assign=' + util.shellquote(oncall),
        '--sub=' + util.shellquote(oncall),
        '--tag=' + util.shellquote(tag),
        '--desc=' + util.shellquote(desc),
        ])
    )
    tasknum = shcmd('tasks view ' + taskid).splitlines()[0].split()[0]
    ui.write(
        _('Task created: https://our.intern.facebook.com/intern/tasks/?t=%s\n')
        % tasknum)
Beispiel #9
0
def uisetup(ui):
    for cmd, path in ui.configitems('extdiff'):
        path = util.expandpath(path)
        if cmd.startswith('cmd.'):
            cmd = cmd[4:]
            if not path:
                path = util.findexe(cmd)
                if path is None:
                    path = filemerge.findexternaltool(ui, cmd) or cmd
            diffopts = ui.config('extdiff', 'opts.' + cmd, '')
            cmdline = util.shellquote(path)
            if diffopts:
                cmdline += ' ' + diffopts
        elif cmd.startswith('opts.'):
            continue
        else:
            if path:
                # case "cmd = path opts"
                cmdline = path
                diffopts = len(shlex.split(cmdline)) > 1
            else:
                # case "cmd ="
                path = util.findexe(cmd)
                if path is None:
                    path = filemerge.findexternaltool(ui, cmd) or cmd
                cmdline = util.shellquote(path)
                diffopts = False
        # look for diff arguments in [diff-tools] then [merge-tools]
        if not diffopts:
            args = ui.config('diff-tools', cmd+'.diffargs') or \
                   ui.config('merge-tools', cmd+'.diffargs')
            if args:
                cmdline += ' ' + args
        def save(cmdline):
            '''use closure to save diff command to use'''
            def mydiff(ui, repo, *pats, **opts):
                options = ' '.join(map(util.shellquote, opts['option']))
                if options:
                    options = ' ' + options
                return dodiff(ui, repo, cmdline + options, pats, opts)
            # We can't pass non-ASCII through docstrings (and path is
            # in an unknown encoding anyway)
            docpath = path.encode("string-escape")
            mydiff.__doc__ = '''\
use %(path)s to diff repository (or selected files)

    Show differences between revisions for the specified files, using
    the %(path)s program.

    When two revision arguments are given, then changes are shown
    between those revisions. If only one revision is specified then
    that revision is compared to the working directory, and, when no
    revisions are specified, the working directory files are compared
    to its parent.\
''' % {'path': util.uirepr(docpath)}
            return mydiff
        command(cmd, extdiffopts[:], _('hg %s [OPTION]... [FILE]...') % cmd,
                inferrepo=True)(save(cmdline))
Beispiel #10
0
def parse_filelist_at_cl(client, cl=None):
    cmd = 'p4 --client %s -G files //%s/...@%d' %(
            util.shellquote(client),
            util.shellquote(client),
            cl
            )
    stdout = util.popen(cmd, mode='rb')
    for d in loaditer(stdout):
        c = d.get('depotFile', None)
        if c:
            yield d
Beispiel #11
0
def parse_filelist(client, startcl=None, endcl=None):
    if startcl is None:
        startcl = 0

    cmd = 'p4 --client %s -G files -a //%s/...%s' % (
            util.shellquote(client),
            util.shellquote(client),
            revrange(startcl, endcl))
    stdout = util.popen(cmd, mode='rb')
    for d in loaditer(stdout):
        c = d.get('depotFile', None)
        if c:
            yield d
Beispiel #12
0
def parse_where(client, depotname):
    # TODO: investigate if we replace this with exactly one call to
    # where //clientame/...
    cmd = 'p4 --client %s -G where %s' % (
            util.shellquote(client),
            util.shellquote(depotname))
    try:
        stdout = ''
        @retry(num=3, sleeps=0.3)
        def helper():
            global stdout
            stdout = util.popen(cmd, mode='rb')
            return marshal.load(stdout)
        return helper()
    except Exception:
        raise P4Exception(stdout)
Beispiel #13
0
 def content(self, rev):
     text = None
     if os.path.isfile(self.rcspath):
         cmd = 'co -kk -q -p1.%d %s' % (rev, util.shellquote(self.rcspath))
         with util.popen(cmd, mode='rb') as fp:
             text = fp.read()
     return text
 def _getlog(self,
             paths,
             start,
             end,
             limit=0,
             discover_changed_paths=True,
             strict_node_history=False):
     # Normalize path names, svn >= 1.5 only wants paths relative to
     # supplied URL
     relpaths = []
     for p in paths:
         if not p.startswith('/'):
             p = self.module + '/' + p
         relpaths.append(p.strip('/'))
     args = [
         self.baseurl, relpaths, start, end, limit, discover_changed_paths,
         strict_node_history
     ]
     arg = encodeargs(args)
     hgexe = util.hgexecutable()
     cmd = '%s debugsvnlog' % util.shellquote(hgexe)
     stdin, stdout = util.popen2(cmd)
     stdin.write(arg)
     stdin.close()
     return logstream(stdout)
Beispiel #15
0
def _findeditor(repo, files):
    '''returns tuple of editor name and editor path.

    tools matched by pattern are returned as (name, toolpath)
    tools detected by search are returned as (name, toolpath)
    tortoisehg.editor is returned as         (None, tortoisehg.editor)
    HGEDITOR or ui.editor are returned as    (None, ui.editor)

    So first return value is an [editor-tool] name or None and
    second return value is a toolpath or user configured command line
    '''
    ui = repo.ui

    # first check for tool specified by file patterns.  The first file pattern
    # which matches one of the files being edited selects the editor
    for pat, tool in ui.configitems("editor-patterns"):
        mf = match.match(repo.root, '', [pat])
        toolpath = _findtool(ui, tool)
        if mf(files[0]) and toolpath:
            return (tool, util.shellquote(toolpath))

    # then editor-tools
    tools = {}
    for k, v in ui.configitems("editor-tools"):
        t = k.split('.')[0]
        if t not in tools:
            try:
                priority = int(_toolstr(ui, t, "priority", "0"))
            except ValueError, e:
                priority = -100
            tools[t] = priority
Beispiel #16
0
def lsfiles(ui, repo, *args, **kwargs):
    cmdoptions = [
        ('c', 'cached', None, ''),
        ('d', 'deleted', None, ''),
        ('m', 'modified', None, ''),
        ('o', 'others', None, ''),
        ('i', 'ignored', None, ''),
        ('s', 'stage', None, ''),
        ('z', '_zero', None, ''),
    ]
    args, opts = parseoptions(ui, cmdoptions, args)

    if (opts.get('modified') or opts.get('deleted')
        or opts.get('others') or opts.get('ignored')):
        cmd = Command('status')
        if opts.get('deleted'):
            cmd['-d'] = None
        if opts.get('modified'):
            cmd['-m'] = None
        if opts.get('others'):
            cmd['-o'] = None
        if opts.get('ignored'):
            cmd['-i'] = None
    else:
        cmd = Command('files')
    if opts.get('stage'):
        ui.status(_("note: Mercurial doesn't have a staging area, ignoring "
                  "--stage\n"))
    if opts.get('_zero'):
        cmd['-0'] = None
    cmd.append('.')
    for include in args:
        cmd['-I'] = util.shellquote(include)

    ui.status((str(cmd)), "\n")
Beispiel #17
0
def _findeditor(repo, files):
    '''returns tuple of editor name and editor path.

    tools matched by pattern are returned as (name, toolpath)
    tools detected by search are returned as (name, toolpath)
    tortoisehg.editor is returned as         (None, tortoisehg.editor)
    HGEDITOR or ui.editor are returned as    (None, ui.editor)

    So first return value is an [editor-tool] name or None and
    second return value is a toolpath or user configured command line
    '''
    ui = repo.ui

    # first check for tool specified by file patterns.  The first file pattern
    # which matches one of the files being edited selects the editor
    for pat, tool in ui.configitems("editor-patterns"):
        mf = match.match(repo.root, '', [pat])
        toolpath = _findtool(ui, tool)
        if mf(files[0]) and toolpath:
            return (tool, util.shellquote(toolpath))

    # then editor-tools
    tools = {}
    for k, v in ui.configitems("editor-tools"):
        t = k.split('.')[0]
        if t not in tools:
            try:
                priority = int(_toolstr(ui, t, "priority", "0"))
            except ValueError, e:
                priority = -100
            tools[t] = priority
Beispiel #18
0
def launchtool(cmd, opts, replace, block):
    def quote(match):
        key = match.group()[1:]
        return util.shellquote(replace[key])
    if isinstance(cmd, unicode):
        cmd = hglib.fromunicode(cmd)
    lopts = []
    for opt in opts:
        if isinstance(opt, unicode):
            lopts.append(hglib.fromunicode(opt))
        else:
            lopts.append(opt)
    args = ' '.join(lopts)
    args = re.sub(_regex, quote, args)
    cmdline = util.shellquote(cmd) + ' ' + args
    cmdline = util.quotecommand(cmdline)
    try:
        proc = subprocess.Popen(cmdline, shell=True,
                                creationflags=qtlib.openflags,
                                stderr=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stdin=subprocess.PIPE)
        if block:
            proc.communicate()
    except (OSError, EnvironmentError), e:
        QMessageBox.warning(None,
                _('Tool launch failure'),
                _('%s : %s') % (cmd, str(e)))
Beispiel #19
0
def launchtool(cmd, opts, replace, block):
    def quote(match):
        key = match.group()[1:]
        return util.shellquote(replace[key])

    if isinstance(cmd, unicode):
        cmd = hglib.fromunicode(cmd)
    lopts = []
    for opt in opts:
        if isinstance(opt, unicode):
            lopts.append(hglib.fromunicode(opt))
        else:
            lopts.append(opt)
    args = ' '.join(lopts)
    args = re.sub(_regex, quote, args)
    cmdline = util.shellquote(cmd) + ' ' + args
    cmdline = util.quotecommand(cmdline)
    try:
        proc = subprocess.Popen(cmdline,
                                shell=True,
                                creationflags=qtlib.openflags,
                                stderr=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stdin=subprocess.PIPE)
        if block:
            proc.communicate()
    except (OSError, EnvironmentError), e:
        QMessageBox.warning(None, _('Tool launch failure'),
                            _('%s : %s') % (cmd, str(e)))
Beispiel #20
0
 def _getlog(self,
             paths,
             start,
             end,
             limit=0,
             discover_changed_paths=True,
             strict_node_history=False):
     # Normalize path names, svn >= 1.5 only wants paths relative to
     # supplied URL
     relpaths = []
     for p in paths:
         if not p.startswith('/'):
             p = self.module + '/' + p
         relpaths.append(p.strip('/'))
     args = [
         self.baseurl, relpaths, start, end, limit, discover_changed_paths,
         strict_node_history
     ]
     arg = encodeargs(args)
     hgexe = util.hgexecutable()
     cmd = '%s debugsvnlog' % util.shellquote(hgexe)
     stdin, stdout = util.popen2(util.quotecommand(cmd))
     stdin.write(arg)
     try:
         stdin.close()
     except IOError:
         raise util.Abort(
             _('Mercurial failed to run itself, check'
               ' hg executable is in PATH'))
     return logstream(stdout)
Beispiel #21
0
 def _execute(self, cmd, *args, **kwargs):
     cmdline = [self.execmd, cmd]
     cmdline += args
     cmdline = [util.shellquote(arg) for arg in cmdline]
     cmdline += ['>', os.devnull, '2>', os.devnull]
     cmdline = util.quotecommand(' '.join(cmdline))
     self.ui.debug(cmdline, '\n')
     return os.system(cmdline)
Beispiel #22
0
 def _parse_view(self, path):
     "Read changes affecting the path"
     cmd = 'p4 -G changes -s submitted %s' % util.shellquote(path)
     stdout = util.popen(cmd, mode='rb')
     for d in loaditer(stdout):
         c = d.get("change", None)
         if c:
             self.p4changes[c] = True
Beispiel #23
0
 def _parse_view(self, path):
     "Read changes affecting the path"
     cmd = 'p4 -G changes -s submitted %s' % util.shellquote(path)
     stdout = util.popen(cmd, mode='rb')
     for d in loaditer(stdout):
         c = d.get("change", None)
         if c:
             self.p4changes[c] = True
Beispiel #24
0
 def _execute(self, cmd, *args, **kwargs):
     cmdline = [self.execmd, cmd]
     cmdline += args
     cmdline = [util.shellquote(arg) for arg in cmdline]
     cmdline += ['>', os.devnull, '2>', os.devnull]
     cmdline = util.quotecommand(' '.join(cmdline))
     self.ui.debug(cmdline, '\n')
     return os.system(cmdline)
Beispiel #25
0
def main():
    args = sys.argv[1:]
    if len(args) not in (2, 4):
        print 'Two or four arguments expected:'
        print sys.argv[0], '[local] [other]'
        print sys.argv[0], '[local] [base] [other] [output]'
        sys.exit(1)
    elif len(args) == 2:
        local, other = [os.path.abspath(f) for f in args]
        _base, ext = os.path.splitext(local)
    else:
        local, base, other, output = [os.path.abspath(f) for f in args]
        _base, ext = os.path.splitext(output)

    if not ext or ext.lower()[1:] not in scripts.keys():
        print 'Unsupported file type', ext
        sys.exit(1)

    proc = win32api.GetCurrentProcess()
    try:
        # This will fail on windows < NT
        filename = win32process.GetModuleFileNameEx(proc, 0)
    except:
        filename = win32api.GetModuleFileName(0)
    path = os.path.join(os.path.dirname(filename), 'diff-scripts')
    if not os.path.isdir(path):
        print 'Diff scripts not found at', path
        sys.exit(1)

    use = scripts[ext.lower()[1:]]

    if 'xls' in use[0] and os.path.basename(local) == os.path.basename(other):
        # XLS hack; Excel will not diff two files if they have the same
        # basename.
        othertmp = other + '~x1'
        shutil.copy(other, othertmp)
        other = othertmp

    if len(args) == 2:
        script = os.path.join(path, use[0])
        cmd = ['wscript', script, other, local]
    elif len(use) == 1:
        print 'Unsupported file type for merge', local
        sys.exit(1)
    else:
        script = os.path.join(path, use[1])
        cmd = ['wscript', script, output, other, local, base]

    encoding = locale.getpreferredencoding(do_setlocale=True)
    cmd = [util.shellquote(safe_encode(arg, encoding)) for arg in cmd]
    cmdline = util.quotecommand(' '.join(cmd))
    proc = subprocess.Popen(cmdline,
                            shell=True,
                            creationflags=win32con.CREATE_NO_WINDOW,
                            stderr=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stdin=subprocess.PIPE)
    return proc.communicate()
Beispiel #26
0
def main():
    args = sys.argv[1:]
    if len(args) not in (2, 4):
        print 'Two or four arguments expected:'
        print sys.argv[0], '[local] [other]'
        print sys.argv[0], '[local] [base] [other] [output]'
        sys.exit(1)
    elif len(args) == 2:
        local, other = [os.path.abspath(f) for f in args]
        base, ext = os.path.splitext(local)
    else:
        local, base, other, output = [os.path.abspath(f) for f in args]
        base, ext = os.path.splitext(output)

    if not ext or ext.lower()[1:] not in scripts.keys():
        print 'Unsupported file type', ext
        sys.exit(1)

    proc = win32api.GetCurrentProcess()
    try:
        # This will fail on windows < NT
        filename = win32process.GetModuleFileNameEx(proc, 0)
    except:
        filename = win32api.GetModuleFileName(0)
    path = os.path.join(os.path.dirname(filename), 'diff-scripts')
    if not os.path.isdir(path):
        print 'Diff scripts not found at', path
        sys.exit(1)

    use = scripts[ext.lower()[1:]]

    if 'xls' in use[0] and os.path.basename(local) == os.path.basename(other):
        # XLS hack; Excel will not diff two files if they have the same
        # basename.
        othertmp = other+'~x1'
        shutil.copy(other, othertmp)
        other = othertmp

    if len(args) == 2:
        script = os.path.join(path, use[0])
        cmd = ['wscript', script, other, local]
    elif len(use) == 1:
        print 'Unsupported file type for merge', local
        sys.exit(1)
    else:
        script = os.path.join(path, use[1])
        cmd = ['wscript', script, output, other, local, base]

    encoding = locale.getpreferredencoding(do_setlocale=True)
    cmd = [util.shellquote(safe_encode(arg, encoding)) for arg in cmd]
    cmdline = util.quotecommand(' '.join(cmd))
    proc = subprocess.Popen(cmdline, shell=True,
                            creationflags=win32con.CREATE_NO_WINDOW,
                            stderr=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stdin=subprocess.PIPE)
    return proc.communicate()
Beispiel #27
0
def get_latest_cl(client):
    cmd = 'p4 --client %s -G changes -m 1 -s submitted' % (
            util.shellquote(client))
    stdout = util.popen(cmd, mode='rb')
    parsed = marshal.load(stdout)
    cl = parsed.get('change')
    if cl:
        return int(cl)
    return None
Beispiel #28
0
 def run_command(self, host, command, username=None, port=None):
     sshcmd = ui.config("ui", "ssh", "ssh")
     args = util.sshargs(sshcmd, host, username, port)
     cmd = '%s %s %s' % (sshcmd, args,
                         util.shellquote(''.join(command)))
     ui.debug('calling ssh: %s\n' % cmd)
     proc = subprocess.Popen(util.quotecommand(cmd), shell=True,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE)
     return SubprocessWrapper(proc)
Beispiel #29
0
def parse_changes(client, startcl=None, endcl=None):
    "Read changes affecting the path"
    cmd = 'p4 --client %s -ztag -G changes -s submitted //%s/...%s' % (
        util.shellquote(client),
        util.shellquote(client),
        revrange(startcl, endcl))

    stdout = util.popen(cmd, mode='rb')
    cur_time = time.time()
    for d in loaditer(stdout):
        c = d.get("change", None)
        oc = d.get("oldChange", None)
        user = d.get("user", None)
        commit_time = d.get("time", None)
        time_diff = (cur_time - int(commit_time)) if commit_time else 0
        if oc:
            yield P4Changelist(int(oc), int(c), user, time_diff)
        elif c:
            yield P4Changelist(int(c), int(c), user, time_diff)
Beispiel #30
0
 def run_command(self, host, command, username=None, port=None):
     sshcmd = ui.config("ui", "ssh", "ssh")
     args = util.sshargs(sshcmd, host, username, port)
     cmd = '%s %s %s' % (sshcmd, args, util.shellquote(
         ' '.join(command)))
     ui.debug('calling ssh: %s\n' % cmd)
     proc = subprocess.Popen(util.quotecommand(cmd),
                             shell=True,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE)
     return SubprocessWrapper(proc)
Beispiel #31
0
 def revisions(self):
     revs = set()
     if os.path.isfile(self.rcspath):
         stdout = util.popen('rlog %s 2>%s'
                             % (util.shellquote(self.rcspath), os.devnull),
                             mode='rb')
         for l in stdout.readlines():
             m = re.match('revision 1.(\d+)', l)
             if m:
                 revs.add(int(m.group(1)))
     return revs
Beispiel #32
0
def parse_fstat(clnum, client, filter=None):
    cmd = 'p4 --client %s -G fstat -e %d -T ' \
          '"depotFile,headAction,headType,headRev" "//%s/..."' % (
            util.shellquote(client),
            clnum,
            util.shellquote(client))
    stdout = util.popen(cmd, mode='rb')
    try:
        result = []
        for d in loaditer(stdout):
            if d.get('depotFile') and (filter is None or filter(d)):
                if d['headAction'] in ACTION_ARCHIVE:
                    continue
                result.append({
                    'depotFile': d['depotFile'],
                    'action': d['headAction'],
                    'type': d['headType'],
                })
        return result
    except Exception:
        raise P4Exception(stdout)
Beispiel #33
0
def get_ui():
    ui_ = ui.ui()
    ui_.fout = ui_.ferr
    ui_.setconfig('progress', 'disable', True)
    ui_.readconfig(os.path.join(git_dir, 'hgrc'))
    ssh = os.environ.get('GIT_SSH_COMMAND')
    if not ssh:
        ssh = os.environ.get('GIT_SSH')
        if ssh:
            ssh = util.shellquote(ssh)
    if ssh:
        ui_.setconfig('ui', 'ssh', ssh)
    return ui_
Beispiel #34
0
def get_ui():
    ui_ = ui.ui()
    ui_.fout = ui_.ferr
    ui_.setconfig('progress', 'disable', True)
    ui_.readconfig(os.path.join(git_dir, 'hgrc'))
    ssh = os.environ.get('GIT_SSH_COMMAND')
    if not ssh:
        ssh = os.environ.get('GIT_SSH')
        if ssh:
            ssh = util.shellquote(ssh)
    if ssh:
        ui_.setconfig('ui', 'ssh', ssh)
    return ui_
Beispiel #35
0
def get_ui():
    ui_ = ui.ui()
    ui_.fout = ui_.ferr
    ui_.setconfig('ui', 'interactive', False)
    ui_.setconfig('progress', 'disable', True)
    ssh = os.environ.get('GIT_SSH_COMMAND')
    if not ssh:
        ssh = os.environ.get('GIT_SSH')
        if ssh:
            ssh = util.shellquote(ssh)
    if ssh:
        ui_.setconfig('ui', 'ssh', ssh)
    return ui_
Beispiel #36
0
def get_ui():
    if not changegroup:
        return None
    ui_ = ui.ui()
    ui_.fout = ui_.ferr
    ui_.setconfig('ui', 'interactive', False)
    ui_.setconfig('progress', 'disable', True)
    ssh = os.environ.get('GIT_SSH_COMMAND')
    if not ssh:
        ssh = os.environ.get('GIT_SSH')
        if ssh:
            ssh = util.shellquote(ssh)
    if ssh:
        ui_.setconfig('ui', 'ssh', ssh)
    return ui_
Beispiel #37
0
def get_file(path, rev=None, clnum=None):
    """Returns a file from Perforce"""
    r = '#head'
    if rev:
        r = '#%d' % rev
    if clnum:
        r = '@%d' % clnum

    cmd = 'p4 print -q %s%s' % (util.shellquote(path), r)
    @retry(num=5, sleeps=0.3)
    def helper():
        stdout = util.popen(cmd, mode='rb')
        content = stdout.read()
        return content
    return helper()
Beispiel #38
0
def exists_client(client):
    cmd = 'p4 -G clients -e %s' % util.shellquote(client)
    try:
        stdout = ''
        @retry(num=3, sleeps=0.3)
        def helper():
            stdout = util.popen(cmd, mode='rb')
            for each in loaditer(stdout):
                client_name = each.get('client', None)
                if client_name is not None and client_name == client:
                    return True
            return False
        return helper()
    except Exception:
        raise P4Exception(stdout)
Beispiel #39
0
        def connect_ssh(self, host, command, username=None, port=None):
            from dulwich.client import SubprocessWrapper
            from mercurial import util
            import subprocess

            sshcmd = ui.config("ui", "ssh", "ssh")
            args = util.sshargs(sshcmd, host, username, port)
            cmd = '%s %s %s' % (sshcmd, args, 
                                util.shellquote(' '.join(command)))
            ui.debug('calling ssh: %s\n' % cmd)
            print command
            proc = subprocess.Popen(util.quotecommand(cmd), shell=True,
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE)
            return SubprocessWrapper(proc)
 def run_command(self, host, command, username=None, port=None):
     # newer dulwich changes the way they pass command and parameters
     # around, so we detect that here and reformat it back to what
     # hg-git expects (e.g. "command 'arg1 arg2'")
     if len(command) > 1:
         command = ["%s '%s'" % (command[0], ' '.join(command[1:]))]
     sshcmd = ui.config("ui", "ssh", "ssh")
     args = util.sshargs(sshcmd, host, username, port)
     cmd = '%s %s %s' % (sshcmd, args,
                         util.shellquote(' '.join(command)))
     ui.debug('calling ssh: %s\n' % cmd)
     proc = subprocess.Popen(util.quotecommand(cmd), shell=True,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE)
     return SubprocessWrapper(proc)
Beispiel #41
0
        def connect_ssh(self, host, command, username=None, port=None):
            from dulwich.client import SubprocessWrapper
            from mercurial import util
            import subprocess

            sshcmd = ui.config("ui", "ssh", "ssh")
            args = util.sshargs(sshcmd, host, username, port)
            cmd = '%s %s %s' % (sshcmd, args, util.shellquote(
                ' '.join(command)))
            ui.debug('calling ssh: %s\n' % cmd)
            print command
            proc = subprocess.Popen(util.quotecommand(cmd),
                                    shell=True,
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE)
            return SubprocessWrapper(proc)
Beispiel #42
0
def editfiles(repo, files, lineno=None, search=None, parent=None, editor=None):
    if len(files) == 1:
        filename = files[0].strip()
        if not filename:
            return
        files = [filename]
        path = repo.wjoin(filename)
        cwd = os.path.dirname(path)
        files = [os.path.basename(path)]
    else:
        cwd = repo.root
    files = [util.shellquote(util.localpath(f)) for f in files]
    editor = repo.ui.config('tortoisehg', 'editor')
    assert len(files) == 1 or lineno == None
    if not editor:
        editor = repo.ui.config('tortoisehg', 'editor')
    if editor:
        try:
            regexp = re.compile('\[([^\]]*)\]')
            expanded = []
            pos = 0
            for m in regexp.finditer(editor):
                expanded.append(editor[pos:m.start()-1])
                phrase = editor[m.start()+1:m.end()-1]
                pos = m.end()+1
                if '$LINENUM' in phrase:
                    if lineno is None:
                        # throw away phrase
                        continue
                    phrase = phrase.replace('$LINENUM', str(lineno))
                elif '$SEARCH' in phrase:
                    if search is None:
                        # throw away phrase
                        continue
                    phrase = phrase.replace('$SEARCH', search)
                if '$FILE' in phrase:
                    phrase = phrase.replace('$FILE', files[0])
                    files = []
                expanded.append(phrase)
            expanded.append(editor[pos:])
            cmdline = ' '.join(expanded + files)
        except ValueError, e:
            # '[' or ']' not found
            cmdline = ' '.join([editor] + files)
        except TypeError, e:
            # variable expansion failed
            cmdline = ' '.join([editor] + files)
Beispiel #43
0
def editfiles(repo, files, lineno=None, search=None, parent=None, editor=None):
    if len(files) == 1:
        filename = files[0].strip()
        if not filename:
            return
        files = [filename]
        path = repo.wjoin(filename)
        cwd = os.path.dirname(path)
        files = [os.path.basename(path)]
    else:
        cwd = repo.root
    files = [util.shellquote(util.localpath(f)) for f in files]
    editor = repo.ui.config('tortoisehg', 'editor')
    assert len(files) == 1 or lineno == None
    if not editor:
        editor = repo.ui.config('tortoisehg', 'editor')
    if editor:
        try:
            regexp = re.compile('\[([^\]]*)\]')
            expanded = []
            pos = 0
            for m in regexp.finditer(editor):
                expanded.append(editor[pos:m.start() - 1])
                phrase = editor[m.start() + 1:m.end() - 1]
                pos = m.end() + 1
                if '$LINENUM' in phrase:
                    if lineno is None:
                        # throw away phrase
                        continue
                    phrase = phrase.replace('$LINENUM', str(lineno))
                elif '$SEARCH' in phrase:
                    if search is None:
                        # throw away phrase
                        continue
                    phrase = phrase.replace('$SEARCH', search)
                if '$FILE' in phrase:
                    phrase = phrase.replace('$FILE', files[0])
                    files = []
                expanded.append(phrase)
            expanded.append(editor[pos:])
            cmdline = ' '.join(expanded + files)
        except ValueError, e:
            # '[' or ']' not found
            cmdline = ' '.join([editor] + files)
        except TypeError, e:
            # variable expansion failed
            cmdline = ' '.join([editor] + files)
Beispiel #44
0
 def run_command(self, host, command, username=None, port=None):
     if isinstance(command, basestring):
         # 0.12.x dulwich sends the raw string
         command = [command]
     elif len(command) > 1:
         # 0.11.x dulwich sends an array of [command arg1 arg2 ...], so
         # we detect that here and reformat it back to what hg-git
         # expects (e.g. "command 'arg1 arg2'")
         command = ["%s '%s'" % (command[0], ' '.join(command[1:]))]
     sshcmd = ui.config("ui", "ssh", "ssh")
     args = util.sshargs(sshcmd, host, username, port)
     cmd = '%s %s %s' % (sshcmd, args,
                         util.shellquote(' '.join(command)))
     ui.debug('calling ssh: %s\n' % cmd)
     proc = subprocess.Popen(util.quotecommand(cmd), shell=True,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE)
     return SubprocessWrapper(proc)
Beispiel #45
0
 def _getlog(self, paths, start, end, limit=0, discover_changed_paths=True,
             strict_node_history=False):
     # Normalize path names, svn >= 1.5 only wants paths relative to
     # supplied URL
     relpaths = []
     for p in paths:
         if not p.startswith('/'):
             p = self.module + '/' + p
         relpaths.append(p.strip('/'))
     args = [self.baseurl, relpaths, start, end, limit, discover_changed_paths,
             strict_node_history]
     arg = encodeargs(args)
     hgexe = util.hgexecutable()
     cmd = '%s debugsvnlog' % util.shellquote(hgexe)
     stdin, stdout = util.popen2(cmd)
     stdin.write(arg)
     stdin.close()
     return logstream(stdout)
Beispiel #46
0
 def _cmdline(self, cmd, *args, **kwargs):
     cmdline = [self.command, cmd] + list(args)
     for k, v in kwargs.iteritems():
         if len(k) == 1:
             cmdline.append('-' + k)
         else:
             cmdline.append('--' + k.replace('_', '-'))
         try:
             if len(k) == 1:
                 cmdline.append('' + v)
             else:
                 cmdline[-1] += '=' + v
         except TypeError:
             pass
     cmdline = [util.shellquote(arg) for arg in cmdline]
     cmdline += ['2>', util.nulldev, '<', util.nulldev]
     cmdline = ' '.join(cmdline)
     return cmdline
Beispiel #47
0
    def getfile(self, name, rev):
        cmd = 'p4 -G print %s' \
            % util.shellquote("%s#%s" % (self.depotname[name], rev))
        stdout = util.popen(cmd, mode='rb')

        mode = None
        contents = ""
        keywords = None

        for d in loaditer(stdout):
            code = d["code"]
            data = d.get("data")

            if code == "error":
                raise IOError(d["generic"], data)

            elif code == "stat":
                if d.get("action") == "purge":
                    return None, None
                p4type = self.re_type.match(d["type"])
                if p4type:
                    mode = ""
                    flags = (p4type.group(1) or "") + (p4type.group(3) or "")
                    if "x" in flags:
                        mode = "x"
                    if p4type.group(2) == "symlink":
                        mode = "l"
                    if "ko" in flags:
                        keywords = self.re_keywords_old
                    elif "k" in flags:
                        keywords = self.re_keywords

            elif code == "text" or code == "binary":
                contents += data

        if mode is None:
            return None, None

        if keywords:
            contents = keywords.sub("$\\1$", contents)
        if mode == "l" and contents.endswith("\n"):
            contents = contents[:-1]

        return contents, mode
Beispiel #48
0
 def run_command(self, host, command, username=None, port=None):
     if isinstance(command, basestring):
         # 0.12.x dulwich sends the raw string
         command = [command]
     elif len(command) > 1:
         # 0.11.x dulwich sends an array of [command arg1 arg2 ...], so
         # we detect that here and reformat it back to what hg-git
         # expects (e.g. "command 'arg1 arg2'")
         command = ["%s '%s'" % (command[0], ' '.join(command[1:]))]
     sshcmd = ui.config("ui", "ssh", "ssh")
     args = util.sshargs(sshcmd, host, username, port)
     cmd = '%s %s %s' % (sshcmd, args, util.shellquote(
         ' '.join(command)))
     ui.debug('calling ssh: %s\n' % cmd)
     proc = subprocess.Popen(util.quotecommand(cmd),
                             shell=True,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE)
     return SubprocessWrapper(proc)
def lsfiles(ui, repo, *args, **kwargs):
    cmdoptions = [
        ('c', 'cached', None, ''),
        ('d', 'deleted', None, ''),
        ('m', 'modified', None, ''),
        ('o', 'others', None, ''),
        ('i', 'ignored', None, ''),
        ('s', 'stage', None, ''),
        ('z', '_zero', None, ''),
    ]
    args, opts = parseoptions(ui, cmdoptions, args)

    if (opts.get('modified') or opts.get('deleted') or opts.get('others')
            or opts.get('ignored')):
        cmd = Command('status')
        if opts.get('deleted'):
            cmd['-d'] = None
        if opts.get('modified'):
            cmd['-m'] = None
        if opts.get('others'):
            cmd['-o'] = None
        if opts.get('ignored'):
            cmd['-i'] = None
    else:
        cmd = Command('files')
    if opts.get('stage'):
        ui.status(
            _("note: Mercurial doesn't have a staging area, ignoring "
              "--stage\n"))
    if opts.get('_zero'):
        cmd['-0'] = None
    cmd.append('.')
    for include in args:
        cmd['-I'] = util.shellquote(include)

    ui.status((str(cmd)), "\n")
Beispiel #50
0
 def quote(match):
     pre = match.group(2)
     key = match.group(3)
     if not do3way and key == 'parent2':
         return pre
     return pre + util.shellquote(replace[key])
    def _parse(self, ui, path):
        "Prepare list of P4 filenames and revisions to import"
        p4changes = {}
        changeset = {}
        files_map = {}
        copies_map = {}
        localname = {}
        depotname = {}
        heads = []

        ui.status(_('reading p4 views\n'))

        # read client spec or view
        if "/" in path:
            p4changes.update(self._parse_view(path))
            if path.startswith("//") and path.endswith("/..."):
                views = {path[:-3]: ""}
            else:
                views = {"//": ""}
        else:
            cmd = 'p4 -G client -o %s' % util.shellquote(path)
            clientspec = marshal.load(util.popen(cmd, mode='rb'))

            views = {}
            for client in clientspec:
                if client.startswith("View"):
                    sview, cview = clientspec[client].split()
                    p4changes.update(self._parse_view(sview))
                    if sview.endswith("...") and cview.endswith("..."):
                        sview = sview[:-3]
                        cview = cview[:-3]
                    cview = cview[2:]
                    cview = cview[cview.find("/") + 1:]
                    views[sview] = cview

        # list of changes that affect our source files
        p4changes = p4changes.keys()
        p4changes.sort(key=int)

        # list with depot pathnames, longest first
        vieworder = views.keys()
        vieworder.sort(key=len, reverse=True)

        # handle revision limiting
        startrev = self.ui.config('convert', 'p4.startrev', default=0)

        # now read the full changelists to get the list of file revisions
        ui.status(_('collecting p4 changelists\n'))
        lastid = None
        for change in p4changes:
            if startrev and int(change) < int(startrev):
                continue
            if self.revs and int(change) > int(self.revs[0]):
                continue
            if change in self.revmap:
                # Ignore already present revisions, but set the parent pointer.
                lastid = change
                continue

            if lastid:
                parents = [lastid]
            else:
                parents = []

            d = self._fetch_revision(change)
            c = self._construct_commit(d, parents)

            descarr = c.desc.splitlines(True)
            if len(descarr) > 0:
                shortdesc = descarr[0].rstrip('\r\n')
            else:
                shortdesc = '**empty changelist description**'

            t = '%s %s' % (c.rev, repr(shortdesc)[1:-1])
            ui.status(util.ellipsis(t, 80) + '\n')

            files = []
            copies = {}
            copiedfiles = []
            i = 0
            while ("depotFile%d" % i) in d and ("rev%d" % i) in d:
                oldname = d["depotFile%d" % i]
                filename = None
                for v in vieworder:
                    if oldname.lower().startswith(v.lower()):
                        filename = decodefilename(views[v] + oldname[len(v):])
                        break
                if filename:
                    files.append((filename, d["rev%d" % i]))
                    depotname[filename] = oldname
                    if (d.get("action%d" % i) == "move/add"):
                        copiedfiles.append(filename)
                    localname[oldname] = filename
                i += 1

            # Collect information about copied files
            for filename in copiedfiles:
                oldname = depotname[filename]

                flcmd = 'p4 -G filelog %s' \
                      % util.shellquote(oldname)
                flstdout = util.popen(flcmd, mode='rb')

                copiedfilename = None
                for d in loaditer(flstdout):
                    copiedoldname = None

                    i = 0
                    while ("change%d" % i) in d:
                        if (d["change%d" % i] == change
                                and d["action%d" % i] == "move/add"):
                            j = 0
                            while ("file%d,%d" % (i, j)) in d:
                                if d["how%d,%d" % (i, j)] == "moved from":
                                    copiedoldname = d["file%d,%d" % (i, j)]
                                    break
                                j += 1
                        i += 1

                    if copiedoldname and copiedoldname in localname:
                        copiedfilename = localname[copiedoldname]
                        break

                if copiedfilename:
                    copies[filename] = copiedfilename
                else:
                    ui.warn(
                        _("cannot find source for copied file: %s@%s\n") %
                        (filename, change))

            changeset[change] = c
            files_map[change] = files
            copies_map[change] = copies
            lastid = change

        if lastid and len(changeset) > 0:
            heads = [lastid]

        return {
            'changeset': changeset,
            'files': files_map,
            'copies': copies_map,
            'heads': heads,
            'depotname': depotname,
        }
Beispiel #52
0
    def _connect(self):
        root = self.cvsroot
        conntype = None
        user, host = None, None
        cmd = ['cvs', 'server']

        self.ui.status(_("connecting to %s\n") % root)

        if root.startswith(":pserver:"):
            root = root[9:]
            m = re.match(r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)',
                         root)
            if m:
                conntype = "pserver"
                user, passw, serv, port, root = m.groups()
                if not user:
                    user = "******"
                if not port:
                    port = 2401
                else:
                    port = int(port)
                format0 = ":pserver:%s@%s:%s" % (user, serv, root)
                format1 = ":pserver:%s@%s:%d%s" % (user, serv, port, root)

                if not passw:
                    passw = "A"
                    cvspass = os.path.expanduser("~/.cvspass")
                    try:
                        pf = open(cvspass)
                        for line in pf.read().splitlines():
                            part1, part2 = line.split(' ', 1)
                            # /1 :pserver:[email protected]:2401/cvsroot/foo
                            # Ah<Z
                            if part1 == '/1':
                                part1, part2 = part2.split(' ', 1)
                                format = format1
                            # :pserver:[email protected]:/cvsroot/foo Ah<Z
                            else:
                                format = format0
                            if part1 == format:
                                passw = part2
                                break
                        pf.close()
                    except IOError as inst:
                        if inst.errno != errno.ENOENT:
                            if not getattr(inst, 'filename', None):
                                inst.filename = cvspass
                            raise

                sck = socket.socket()
                sck.connect((serv, port))
                sck.send("\n".join(["BEGIN AUTH REQUEST", root, user, passw,
                                    "END AUTH REQUEST", ""]))
                if sck.recv(128) != "I LOVE YOU\n":
                    raise util.Abort(_("CVS pserver authentication failed"))

                self.writep = self.readp = sck.makefile('r+')

        if not conntype and root.startswith(":local:"):
            conntype = "local"
            root = root[7:]

        if not conntype:
            # :ext:user@host/home/user/path/to/cvsroot
            if root.startswith(":ext:"):
                root = root[5:]
            m = re.match(r'(?:([^@:/]+)@)?([^:/]+):?(.*)', root)
            # Do not take Windows path "c:\foo\bar" for a connection strings
            if os.path.isdir(root) or not m:
                conntype = "local"
            else:
                conntype = "rsh"
                user, host, root = m.group(1), m.group(2), m.group(3)

        if conntype != "pserver":
            if conntype == "rsh":
                rsh = os.environ.get("CVS_RSH") or "ssh"
                if user:
                    cmd = [rsh, '-l', user, host] + cmd
                else:
                    cmd = [rsh, host] + cmd

            # popen2 does not support argument lists under Windows
            cmd = [util.shellquote(arg) for arg in cmd]
            cmd = util.quotecommand(' '.join(cmd))
            self.writep, self.readp = util.popen2(cmd)

        self.realroot = root

        self.writep.write("Root %s\n" % root)
        self.writep.write("Valid-responses ok error Valid-requests Mode"
                          " M Mbinary E Checked-in Created Updated"
                          " Merged Removed\n")
        self.writep.write("valid-requests\n")
        self.writep.flush()
        r = self.readp.readline()
        if not r.startswith("Valid-requests"):
            raise util.Abort(_('unexpected response from CVS server '
                               '(expected "Valid-requests", but got %r)')
                             % r)
        if "UseUnchanged" in r:
            self.writep.write("UseUnchanged\n")
            self.writep.flush()
            r = self.readp.readline()
    def getfile(self, name, rev):
        cmd = 'p4 -G print %s' \
            % util.shellquote("%s#%s" % (self.depotname[name], rev))

        lasterror = None
        while True:
            stdout = util.popen(cmd, mode='rb')

            mode = None
            contents = []
            keywords = None

            for d in loaditer(stdout):
                code = d["code"]
                data = d.get("data")

                if code == "error":
                    # if this is the first time error happened
                    # re-attempt getting the file
                    if not lasterror:
                        lasterror = IOError(d["generic"], data)
                        # this will exit inner-most for-loop
                        break
                    else:
                        raise lasterror

                elif code == "stat":
                    action = d.get("action")
                    if action in ["purge", "delete", "move/delete"]:
                        return None, None
                    p4type = self.re_type.match(d["type"])
                    if p4type:
                        mode = ""
                        flags = ((p4type.group(1) or "") +
                                 (p4type.group(3) or ""))
                        if "x" in flags:
                            mode = "x"
                        if p4type.group(2) == "symlink":
                            mode = "l"
                        if "ko" in flags:
                            keywords = self.re_keywords_old
                        elif "k" in flags:
                            keywords = self.re_keywords

                elif code == "text" or code == "binary":
                    contents.append(data)

                lasterror = None

            if not lasterror:
                break

        if mode is None:
            return None, None

        contents = ''.join(contents)

        if keywords:
            contents = keywords.sub("$\\1$", contents)
        if mode == "l" and contents.endswith("\n"):
            contents = contents[:-1]

        return contents, mode
Beispiel #54
0
class convert_cvs(converter_source):
    def __init__(self, ui, path, rev=None):
        super(convert_cvs, self).__init__(ui, path, rev=rev)

        cvs = os.path.join(path, "CVS")
        if not os.path.exists(cvs):
            raise NoRepo("%s does not look like a CVS checkout" % path)

        checktool('cvs')
        self.cmd = ui.config('convert', 'cvsps', 'builtin')
        cvspsexe = self.cmd.split(None, 1)[0]
        self.builtin = cvspsexe == 'builtin'
        if not self.builtin:
            ui.warn(
                _('warning: support for external cvsps is deprecated and '
                  'will be removed in Mercurial 1.4\n'))

        if not self.builtin:
            checktool(cvspsexe)

        self.changeset = None
        self.files = {}
        self.tags = {}
        self.lastbranch = {}
        self.parent = {}
        self.socket = None
        self.cvsroot = file(os.path.join(cvs, "Root")).read()[:-1]
        self.cvsrepo = file(os.path.join(cvs, "Repository")).read()[:-1]
        self.encoding = locale.getpreferredencoding()

        self._connect()

    def _parse(self):
        if self.changeset is not None:
            return
        self.changeset = {}

        maxrev = 0
        cmd = self.cmd
        if self.rev:
            # TODO: handle tags
            try:
                # patchset number?
                maxrev = int(self.rev)
            except ValueError:
                try:
                    # date
                    util.parsedate(self.rev, ['%Y/%m/%d %H:%M:%S'])
                    cmd = '%s -d "1970/01/01 00:00:01" -d "%s"' % (cmd,
                                                                   self.rev)
                except util.Abort:
                    raise util.Abort(
                        _('revision %s is not a patchset number or date') %
                        self.rev)

        d = os.getcwd()
        try:
            os.chdir(self.path)
            id = None
            state = 0
            filerevids = {}

            if self.builtin:
                # builtin cvsps code
                self.ui.status(_('using builtin cvsps\n'))

                cache = 'update'
                if not self.ui.configbool('convert', 'cvsps.cache', True):
                    cache = None
                db = cvsps.createlog(self.ui, cache=cache)
                db = cvsps.createchangeset(
                    self.ui,
                    db,
                    fuzz=int(self.ui.config('convert', 'cvsps.fuzz', 60)),
                    mergeto=self.ui.config('convert', 'cvsps.mergeto', None),
                    mergefrom=self.ui.config('convert', 'cvsps.mergefrom',
                                             None))

                for cs in db:
                    if maxrev and cs.id > maxrev:
                        break
                    id = str(cs.id)
                    cs.author = self.recode(cs.author)
                    self.lastbranch[cs.branch] = id
                    cs.comment = self.recode(cs.comment)
                    date = util.datestr(cs.date)
                    self.tags.update(dict.fromkeys(cs.tags, id))

                    files = {}
                    for f in cs.entries:
                        files[f.file] = "%s%s" % ('.'.join(
                            [str(x)
                             for x in f.revision]), ['', '(DEAD)'][f.dead])

                    # add current commit to set
                    c = commit(author=cs.author,
                               date=date,
                               parents=[str(p.id) for p in cs.parents],
                               desc=cs.comment,
                               branch=cs.branch or '')
                    self.changeset[id] = c
                    self.files[id] = files
            else:
                # external cvsps
                for l in util.popen(cmd):
                    if state == 0:  # header
                        if l.startswith("PatchSet"):
                            id = l[9:-2]
                            if maxrev and int(id) > maxrev:
                                # ignore everything
                                state = 3
                        elif l.startswith("Date:"):
                            date = util.parsedate(l[6:-1],
                                                  ["%Y/%m/%d %H:%M:%S"])
                            date = util.datestr(date)
                        elif l.startswith("Branch:"):
                            branch = l[8:-1]
                            self.parent[id] = self.lastbranch.get(
                                branch, 'bad')
                            self.lastbranch[branch] = id
                        elif l.startswith("Ancestor branch:"):
                            ancestor = l[17:-1]
                            # figure out the parent later
                            self.parent[id] = self.lastbranch[ancestor]
                        elif l.startswith("Author:"):
                            author = self.recode(l[8:-1])
                        elif l.startswith("Tag:") or l.startswith("Tags:"):
                            t = l[l.index(':') + 1:]
                            t = [ut.strip() for ut in t.split(',')]
                            if (len(t) > 1) or (t[0] and (t[0] != "(none)")):
                                self.tags.update(dict.fromkeys(t, id))
                        elif l.startswith("Log:"):
                            # switch to gathering log
                            state = 1
                            log = ""
                    elif state == 1:  # log
                        if l == "Members: \n":
                            # switch to gathering members
                            files = {}
                            oldrevs = []
                            log = self.recode(log[:-1])
                            state = 2
                        else:
                            # gather log
                            log += l
                    elif state == 2:  # members
                        if l == "\n":  # start of next entry
                            state = 0
                            p = [self.parent[id]]
                            if id == "1":
                                p = []
                            if branch == "HEAD":
                                branch = ""
                            if branch:
                                latest = 0
                                # the last changeset that contains a base
                                # file is our parent
                                for r in oldrevs:
                                    latest = max(filerevids.get(r, 0), latest)
                                if latest:
                                    p = [latest]

                            # add current commit to set
                            c = commit(author=author,
                                       date=date,
                                       parents=p,
                                       desc=log,
                                       branch=branch)
                            self.changeset[id] = c
                            self.files[id] = files
                        else:
                            colon = l.rfind(':')
                            file = l[1:colon]
                            rev = l[colon + 1:-2]
                            oldrev, rev = rev.split("->")
                            files[file] = rev

                            # save some information for identifying branch points
                            oldrevs.append("%s:%s" % (oldrev, file))
                            filerevids["%s:%s" % (rev, file)] = id
                    elif state == 3:
                        # swallow all input
                        continue

            self.heads = self.lastbranch.values()
        finally:
            os.chdir(d)

    def _connect(self):
        root = self.cvsroot
        conntype = None
        user, host = None, None
        cmd = ['cvs', 'server']

        self.ui.status(_("connecting to %s\n") % root)

        if root.startswith(":pserver:"):
            root = root[9:]
            m = re.match(r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)',
                         root)
            if m:
                conntype = "pserver"
                user, passw, serv, port, root = m.groups()
                if not user:
                    user = "******"
                if not port:
                    port = 2401
                else:
                    port = int(port)
                format0 = ":pserver:%s@%s:%s" % (user, serv, root)
                format1 = ":pserver:%s@%s:%d%s" % (user, serv, port, root)

                if not passw:
                    passw = "A"
                    cvspass = os.path.expanduser("~/.cvspass")
                    try:
                        pf = open(cvspass)
                        for line in pf.read().splitlines():
                            part1, part2 = line.split(' ', 1)
                            if part1 == '/1':
                                # /1 :pserver:[email protected]:2401/cvsroot/foo Ah<Z
                                part1, part2 = part2.split(' ', 1)
                                format = format1
                            else:
                                # :pserver:[email protected]:/cvsroot/foo Ah<Z
                                format = format0
                            if part1 == format:
                                passw = part2
                                break
                        pf.close()
                    except IOError, inst:
                        if inst.errno != errno.ENOENT:
                            if not getattr(inst, 'filename', None):
                                inst.filename = cvspass
                            raise

                sck = socket.socket()
                sck.connect((serv, port))
                sck.send("\n".join([
                    "BEGIN AUTH REQUEST", root, user, passw,
                    "END AUTH REQUEST", ""
                ]))
                if sck.recv(128) != "I LOVE YOU\n":
                    raise util.Abort(_("CVS pserver authentication failed"))

                self.writep = self.readp = sck.makefile('r+')

        if not conntype and root.startswith(":local:"):
            conntype = "local"
            root = root[7:]

        if not conntype:
            # :ext:user@host/home/user/path/to/cvsroot
            if root.startswith(":ext:"):
                root = root[5:]
            m = re.match(r'(?:([^@:/]+)@)?([^:/]+):?(.*)', root)
            # Do not take Windows path "c:\foo\bar" for a connection strings
            if os.path.isdir(root) or not m:
                conntype = "local"
            else:
                conntype = "rsh"
                user, host, root = m.group(1), m.group(2), m.group(3)

        if conntype != "pserver":
            if conntype == "rsh":
                rsh = os.environ.get("CVS_RSH") or "ssh"
                if user:
                    cmd = [rsh, '-l', user, host] + cmd
                else:
                    cmd = [rsh, host] + cmd

            # popen2 does not support argument lists under Windows
            cmd = [util.shellquote(arg) for arg in cmd]
            cmd = util.quotecommand(' '.join(cmd))
            self.writep, self.readp = util.popen2(cmd)

        self.realroot = root

        self.writep.write("Root %s\n" % root)
        self.writep.write("Valid-responses ok error Valid-requests Mode"
                          " M Mbinary E Checked-in Created Updated"
                          " Merged Removed\n")
        self.writep.write("valid-requests\n")
        self.writep.flush()
        r = self.readp.readline()
        if not r.startswith("Valid-requests"):
            raise util.Abort(
                _("unexpected response from CVS server "
                  "(expected \"Valid-requests\", but got %r)") % r)
        if "UseUnchanged" in r:
            self.writep.write("UseUnchanged\n")
            self.writep.flush()
            r = self.readp.readline()
Beispiel #55
0
def uisetup(ui):
    for cmd, path in ui.configitems('extdiff'):
        if cmd.startswith('cmd.'):
            cmd = cmd[4:]
            if not path:
                path = util.findexe(cmd)
                if path is None:
                    path = filemerge.findexternaltool(ui, cmd) or cmd
            diffopts = ui.config('extdiff', 'opts.' + cmd, '')
            cmdline = util.shellquote(path)
            if diffopts:
                cmdline += ' ' + diffopts
        elif cmd.startswith('opts.'):
            continue
        else:
            if path:
                # case "cmd = path opts"
                cmdline = path
                diffopts = len(shlex.split(cmdline)) > 1
            else:
                # case "cmd ="
                path = util.findexe(cmd)
                if path is None:
                    path = filemerge.findexternaltool(ui, cmd) or cmd
                cmdline = util.shellquote(path)
                diffopts = False
        # look for diff arguments in [diff-tools] then [merge-tools]
        if not diffopts:
            args = ui.config('diff-tools', cmd+'.diffargs') or \
                   ui.config('merge-tools', cmd+'.diffargs')
            if args:
                cmdline += ' ' + args

        def save(cmdline):
            '''use closure to save diff command to use'''
            def mydiff(ui, repo, *pats, **opts):
                options = ' '.join(map(util.shellquote, opts['option']))
                if options:
                    options = ' ' + options
                return dodiff(ui, repo, cmdline + options, pats, opts)

            doc = _('''\
use %(path)s to diff repository (or selected files)

    Show differences between revisions for the specified files, using
    the %(path)s program.

    When two revision arguments are given, then changes are shown
    between those revisions. If only one revision is specified then
    that revision is compared to the working directory, and, when no
    revisions are specified, the working directory files are compared
    to its parent.\
''') % {
                'path': util.uirepr(path)
            }

            # We must translate the docstring right away since it is
            # used as a format string. The string will unfortunately
            # be translated again in commands.helpcmd and this will
            # fail when the docstring contains non-ASCII characters.
            # Decoding the string to a Unicode string here (using the
            # right encoding) prevents that.
            mydiff.__doc__ = doc.decode(encoding.encoding)
            return mydiff

        cmdtable[cmd] = (save(cmdline), cmdtable['extdiff'][1][1:],
                         _('hg %s [OPTION]... [FILE]...') % cmd)
Beispiel #56
0
def createlog(ui, directory=None, root="", rlog=True, cache=None):
    '''Collect the CVS rlog'''

    # Because we store many duplicate commit log messages, reusing strings
    # saves a lot of memory and pickle storage space.
    _scache = {}

    def scache(s):
        "return a shared version of a string"
        return _scache.setdefault(s, s)

    ui.status(_('collecting CVS rlog\n'))

    log = []  # list of logentry objects containing the CVS state

    # patterns to match in CVS (r)log output, by state of use
    re_00 = re.compile('RCS file: (.+)$')
    re_01 = re.compile('cvs \\[r?log aborted\\]: (.+)$')
    re_02 = re.compile('cvs (r?log|server): (.+)\n$')
    re_03 = re.compile("(Cannot access.+CVSROOT)|"
                       "(can't create temporary directory.+)$")
    re_10 = re.compile('Working file: (.+)$')
    re_20 = re.compile('symbolic names:')
    re_30 = re.compile('\t(.+): ([\\d.]+)$')
    re_31 = re.compile('----------------------------$')
    re_32 = re.compile('======================================='
                       '======================================$')
    re_50 = re.compile('revision ([\\d.]+)(\s+locked by:\s+.+;)?$')
    re_60 = re.compile(r'date:\s+(.+);\s+author:\s+(.+);\s+state:\s+(.+?);'
                       r'(\s+lines:\s+(\+\d+)?\s+(-\d+)?;)?'
                       r'(\s+commitid:\s+([^;]+);)?'
                       r'(.*mergepoint:\s+([^;]+);)?')
    re_70 = re.compile('branches: (.+);$')

    file_added_re = re.compile(r'file [^/]+ was (initially )?added on branch')

    prefix = ''  # leading path to strip of what we get from CVS

    if directory is None:
        # Current working directory

        # Get the real directory in the repository
        try:
            prefix = open(os.path.join('CVS', 'Repository')).read().strip()
            directory = prefix
            if prefix == ".":
                prefix = ""
        except IOError:
            raise logerror(_('not a CVS sandbox'))

        if prefix and not prefix.endswith(os.sep):
            prefix += os.sep

        # Use the Root file in the sandbox, if it exists
        try:
            root = open(os.path.join('CVS', 'Root')).read().strip()
        except IOError:
            pass

    if not root:
        root = os.environ.get('CVSROOT', '')

    # read log cache if one exists
    oldlog = []
    date = None

    if cache:
        cachedir = os.path.expanduser('~/.hg.cvsps')
        if not os.path.exists(cachedir):
            os.mkdir(cachedir)

        # The cvsps cache pickle needs a uniquified name, based on the
        # repository location. The address may have all sort of nasties
        # in it, slashes, colons and such. So here we take just the
        # alphanumeric characters, concatenated in a way that does not
        # mix up the various components, so that
        #    :pserver:user@server:/path
        # and
        #    /pserver/user/server/path
        # are mapped to different cache file names.
        cachefile = root.split(":") + [directory, "cache"]
        cachefile = ['-'.join(re.findall(r'\w+', s)) for s in cachefile if s]
        cachefile = os.path.join(cachedir,
                                 '.'.join([s for s in cachefile if s]))

    if cache == 'update':
        try:
            ui.note(_('reading cvs log cache %s\n') % cachefile)
            oldlog = pickle.load(open(cachefile))
            for e in oldlog:
                if not (util.safehasattr(e, 'branchpoints')
                        and util.safehasattr(e, 'commitid')
                        and util.safehasattr(e, 'mergepoint')):
                    ui.status(_('ignoring old cache\n'))
                    oldlog = []
                    break

            ui.note(_('cache has %d log entries\n') % len(oldlog))
        except Exception as e:
            ui.note(_('error reading cache: %r\n') % e)

        if oldlog:
            date = oldlog[-1].date  # last commit date as a (time,tz) tuple
            date = util.datestr(date, '%Y/%m/%d %H:%M:%S %1%2')

    # build the CVS commandline
    cmd = ['cvs', '-q']
    if root:
        cmd.append('-d%s' % root)
        p = util.normpath(getrepopath(root))
        if not p.endswith('/'):
            p += '/'
        if prefix:
            # looks like normpath replaces "" by "."
            prefix = p + util.normpath(prefix)
        else:
            prefix = p
    cmd.append(['log', 'rlog'][rlog])
    if date:
        # no space between option and date string
        cmd.append('-d>%s' % date)
    cmd.append(directory)

    # state machine begins here
    tags = {}  # dictionary of revisions on current file with their tags
    branchmap = {}  # mapping between branch names and revision numbers
    rcsmap = {}
    state = 0
    store = False  # set when a new record can be appended

    cmd = [util.shellquote(arg) for arg in cmd]
    ui.note(_("running %s\n") % (' '.join(cmd)))
    ui.debug("prefix=%r directory=%r root=%r\n" % (prefix, directory, root))

    pfp = util.popen(' '.join(cmd))
    peek = pfp.readline()
    while True:
        line = peek
        if line == '':
            break
        peek = pfp.readline()
        if line.endswith('\n'):
            line = line[:-1]
        #ui.debug('state=%d line=%r\n' % (state, line))

        if state == 0:
            # initial state, consume input until we see 'RCS file'
            match = re_00.match(line)
            if match:
                rcs = match.group(1)
                tags = {}
                if rlog:
                    filename = util.normpath(rcs[:-2])
                    if filename.startswith(prefix):
                        filename = filename[len(prefix):]
                    if filename.startswith('/'):
                        filename = filename[1:]
                    if filename.startswith('Attic/'):
                        filename = filename[6:]
                    else:
                        filename = filename.replace('/Attic/', '/')
                    state = 2
                    continue
                state = 1
                continue
            match = re_01.match(line)
            if match:
                raise logerror(match.group(1))
            match = re_02.match(line)
            if match:
                raise logerror(match.group(2))
            if re_03.match(line):
                raise logerror(line)

        elif state == 1:
            # expect 'Working file' (only when using log instead of rlog)
            match = re_10.match(line)
            assert match, _('RCS file must be followed by working file')
            filename = util.normpath(match.group(1))
            state = 2

        elif state == 2:
            # expect 'symbolic names'
            if re_20.match(line):
                branchmap = {}
                state = 3

        elif state == 3:
            # read the symbolic names and store as tags
            match = re_30.match(line)
            if match:
                rev = [int(x) for x in match.group(2).split('.')]

                # Convert magic branch number to an odd-numbered one
                revn = len(rev)
                if revn > 3 and (revn % 2) == 0 and rev[-2] == 0:
                    rev = rev[:-2] + rev[-1:]
                rev = tuple(rev)

                if rev not in tags:
                    tags[rev] = []
                tags[rev].append(match.group(1))
                branchmap[match.group(1)] = match.group(2)

            elif re_31.match(line):
                state = 5
            elif re_32.match(line):
                state = 0

        elif state == 4:
            # expecting '------' separator before first revision
            if re_31.match(line):
                state = 5
            else:
                assert not re_32.match(line), _('must have at least '
                                                'some revisions')

        elif state == 5:
            # expecting revision number and possibly (ignored) lock indication
            # we create the logentry here from values stored in states 0 to 4,
            # as this state is re-entered for subsequent revisions of a file.
            match = re_50.match(line)
            assert match, _('expected revision number')
            e = logentry(rcs=scache(rcs),
                         file=scache(filename),
                         revision=tuple(
                             [int(x) for x in match.group(1).split('.')]),
                         branches=[],
                         parent=None,
                         commitid=None,
                         mergepoint=None,
                         branchpoints=set())

            state = 6

        elif state == 6:
            # expecting date, author, state, lines changed
            match = re_60.match(line)
            assert match, _('revision must be followed by date line')
            d = match.group(1)
            if d[2] == '/':
                # Y2K
                d = '19' + d

            if len(d.split()) != 3:
                # cvs log dates always in GMT
                d = d + ' UTC'
            e.date = util.parsedate(d, [
                '%y/%m/%d %H:%M:%S', '%Y/%m/%d %H:%M:%S', '%Y-%m-%d %H:%M:%S'
            ])
            e.author = scache(match.group(2))
            e.dead = match.group(3).lower() == 'dead'

            if match.group(5):
                if match.group(6):
                    e.lines = (int(match.group(5)), int(match.group(6)))
                else:
                    e.lines = (int(match.group(5)), 0)
            elif match.group(6):
                e.lines = (0, int(match.group(6)))
            else:
                e.lines = None

            if match.group(7):  # cvs 1.12 commitid
                e.commitid = match.group(8)

            if match.group(9):  # cvsnt mergepoint
                myrev = match.group(10).split('.')
                if len(myrev) == 2:  # head
                    e.mergepoint = 'HEAD'
                else:
                    myrev = '.'.join(myrev[:-2] + ['0', myrev[-2]])
                    branches = [b for b in branchmap if branchmap[b] == myrev]
                    assert len(branches) == 1, ('unknown branch: %s' %
                                                e.mergepoint)
                    e.mergepoint = branches[0]

            e.comment = []
            state = 7

        elif state == 7:
            # read the revision numbers of branches that start at this revision
            # or store the commit log message otherwise
            m = re_70.match(line)
            if m:
                e.branches = [
                    tuple([int(y) for y in x.strip().split('.')])
                    for x in m.group(1).split(';')
                ]
                state = 8
            elif re_31.match(line) and re_50.match(peek):
                state = 5
                store = True
            elif re_32.match(line):
                state = 0
                store = True
            else:
                e.comment.append(line)

        elif state == 8:
            # store commit log message
            if re_31.match(line):
                cpeek = peek
                if cpeek.endswith('\n'):
                    cpeek = cpeek[:-1]
                if re_50.match(cpeek):
                    state = 5
                    store = True
                else:
                    e.comment.append(line)
            elif re_32.match(line):
                state = 0
                store = True
            else:
                e.comment.append(line)

        # When a file is added on a branch B1, CVS creates a synthetic
        # dead trunk revision 1.1 so that the branch has a root.
        # Likewise, if you merge such a file to a later branch B2 (one
        # that already existed when the file was added on B1), CVS
        # creates a synthetic dead revision 1.1.x.1 on B2.  Don't drop
        # these revisions now, but mark them synthetic so
        # createchangeset() can take care of them.
        if (store and e.dead and e.revision[-1] == 1 and  # 1.1 or 1.1.x.1
                len(e.comment) == 1 and file_added_re.match(e.comment[0])):
            ui.debug('found synthetic revision in %s: %r\n' %
                     (e.rcs, e.comment[0]))
            e.synthetic = True

        if store:
            # clean up the results and save in the log.
            store = False
            e.tags = sorted([scache(x) for x in tags.get(e.revision, [])])
            e.comment = scache('\n'.join(e.comment))

            revn = len(e.revision)
            if revn > 3 and (revn % 2) == 0:
                e.branch = tags.get(e.revision[:-1], [None])[0]
            else:
                e.branch = None

            # find the branches starting from this revision
            branchpoints = set()
            for branch, revision in branchmap.iteritems():
                revparts = tuple([int(i) for i in revision.split('.')])
                if len(revparts) < 2:  # bad tags
                    continue
                if revparts[-2] == 0 and revparts[-1] % 2 == 0:
                    # normal branch
                    if revparts[:-2] == e.revision:
                        branchpoints.add(branch)
                elif revparts == (1, 1, 1):  # vendor branch
                    if revparts in e.branches:
                        branchpoints.add(branch)
            e.branchpoints = branchpoints

            log.append(e)

            rcsmap[e.rcs.replace('/Attic/', '/')] = e.rcs

            if len(log) % 100 == 0:
                ui.status(
                    util.ellipsis('%d %s' % (len(log), e.file), 80) + '\n')

    log.sort(key=lambda x: (x.rcs, x.revision))

    # find parent revisions of individual files
    versions = {}
    for e in sorted(oldlog, key=lambda x: (x.rcs, x.revision)):
        rcs = e.rcs.replace('/Attic/', '/')
        if rcs in rcsmap:
            e.rcs = rcsmap[rcs]
        branch = e.revision[:-1]
        versions[(e.rcs, branch)] = e.revision

    for e in log:
        branch = e.revision[:-1]
        p = versions.get((e.rcs, branch), None)
        if p is None:
            p = e.revision[:-2]
        e.parent = p
        versions[(e.rcs, branch)] = e.revision

    # update the log cache
    if cache:
        if log:
            # join up the old and new logs
            log.sort(key=lambda x: x.date)

            if oldlog and oldlog[-1].date >= log[0].date:
                raise logerror(
                    _('log cache overlaps with new log entries,'
                      ' re-run without cache.'))

            log = oldlog + log

            # write the new cachefile
            ui.note(_('writing cvs log cache %s\n') % cachefile)
            pickle.dump(log, open(cachefile, 'w'))
        else:
            log = oldlog

    ui.status(_('%d log entries\n') % len(log))

    hook.hook(ui, None, "cvslog", True, log=log)

    return log
Beispiel #57
0
class convert_cvs(converter_source):
    def __init__(self, ui, path, rev=None):
        super(convert_cvs, self).__init__(ui, path, rev=rev)

        cvs = os.path.join(path, "CVS")
        if not os.path.exists(cvs):
            raise NoRepo(_("%s does not look like a CVS checkout") % path)

        checktool('cvs')

        self.changeset = None
        self.files = {}
        self.tags = {}
        self.lastbranch = {}
        self.socket = None
        self.cvsroot = open(os.path.join(cvs, "Root")).read()[:-1]
        self.cvsrepo = open(os.path.join(cvs, "Repository")).read()[:-1]
        self.encoding = encoding.encoding

        self._connect()

    def _parse(self):
        if self.changeset is not None:
            return
        self.changeset = {}

        maxrev = 0
        if self.rev:
            # TODO: handle tags
            try:
                # patchset number?
                maxrev = int(self.rev)
            except ValueError:
                raise util.Abort(_('revision %s is not a patchset number')
                                 % self.rev)

        d = os.getcwd()
        try:
            os.chdir(self.path)
            id = None

            cache = 'update'
            if not self.ui.configbool('convert', 'cvsps.cache', True):
                cache = None
            db = cvsps.createlog(self.ui, cache=cache)
            db = cvsps.createchangeset(self.ui, db,
                fuzz=int(self.ui.config('convert', 'cvsps.fuzz', 60)),
                mergeto=self.ui.config('convert', 'cvsps.mergeto', None),
                mergefrom=self.ui.config('convert', 'cvsps.mergefrom', None))

            for cs in db:
                if maxrev and cs.id > maxrev:
                    break
                id = str(cs.id)
                cs.author = self.recode(cs.author)
                self.lastbranch[cs.branch] = id
                cs.comment = self.recode(cs.comment)
                date = util.datestr(cs.date)
                self.tags.update(dict.fromkeys(cs.tags, id))

                files = {}
                for f in cs.entries:
                    files[f.file] = "%s%s" % ('.'.join([str(x)
                                                        for x in f.revision]),
                                              ['', '(DEAD)'][f.dead])

                # add current commit to set
                c = commit(author=cs.author, date=date,
                           parents=[str(p.id) for p in cs.parents],
                           desc=cs.comment, branch=cs.branch or '')
                self.changeset[id] = c
                self.files[id] = files

            self.heads = self.lastbranch.values()
        finally:
            os.chdir(d)

    def _connect(self):
        root = self.cvsroot
        conntype = None
        user, host = None, None
        cmd = ['cvs', 'server']

        self.ui.status(_("connecting to %s\n") % root)

        if root.startswith(":pserver:"):
            root = root[9:]
            m = re.match(r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)',
                         root)
            if m:
                conntype = "pserver"
                user, passw, serv, port, root = m.groups()
                if not user:
                    user = "******"
                if not port:
                    port = 2401
                else:
                    port = int(port)
                format0 = ":pserver:%s@%s:%s" % (user, serv, root)
                format1 = ":pserver:%s@%s:%d%s" % (user, serv, port, root)

                if not passw:
                    passw = "A"
                    cvspass = os.path.expanduser("~/.cvspass")
                    try:
                        pf = open(cvspass)
                        for line in pf.read().splitlines():
                            part1, part2 = line.split(' ', 1)
                            if part1 == '/1':
                                # /1 :pserver:[email protected]:2401/cvsroot/foo Ah<Z
                                part1, part2 = part2.split(' ', 1)
                                format = format1
                            else:
                                # :pserver:[email protected]:/cvsroot/foo Ah<Z
                                format = format0
                            if part1 == format:
                                passw = part2
                                break
                        pf.close()
                    except IOError, inst:
                        if inst.errno != errno.ENOENT:
                            if not getattr(inst, 'filename', None):
                                inst.filename = cvspass
                            raise

                sck = socket.socket()
                sck.connect((serv, port))
                sck.send("\n".join(["BEGIN AUTH REQUEST", root, user, passw,
                                    "END AUTH REQUEST", ""]))
                if sck.recv(128) != "I LOVE YOU\n":
                    raise util.Abort(_("CVS pserver authentication failed"))

                self.writep = self.readp = sck.makefile('r+')

        if not conntype and root.startswith(":local:"):
            conntype = "local"
            root = root[7:]

        if not conntype:
            # :ext:user@host/home/user/path/to/cvsroot
            if root.startswith(":ext:"):
                root = root[5:]
            m = re.match(r'(?:([^@:/]+)@)?([^:/]+):?(.*)', root)
            # Do not take Windows path "c:\foo\bar" for a connection strings
            if os.path.isdir(root) or not m:
                conntype = "local"
            else:
                conntype = "rsh"
                user, host, root = m.group(1), m.group(2), m.group(3)

        if conntype != "pserver":
            if conntype == "rsh":
                rsh = os.environ.get("CVS_RSH") or "ssh"
                if user:
                    cmd = [rsh, '-l', user, host] + cmd
                else:
                    cmd = [rsh, host] + cmd

            # popen2 does not support argument lists under Windows
            cmd = [util.shellquote(arg) for arg in cmd]
            cmd = util.quotecommand(' '.join(cmd))
            self.writep, self.readp = util.popen2(cmd)

        self.realroot = root

        self.writep.write("Root %s\n" % root)
        self.writep.write("Valid-responses ok error Valid-requests Mode"
                          " M Mbinary E Checked-in Created Updated"
                          " Merged Removed\n")
        self.writep.write("valid-requests\n")
        self.writep.flush()
        r = self.readp.readline()
        if not r.startswith("Valid-requests"):
            raise util.Abort(_('unexpected response from CVS server '
                               '(expected "Valid-requests", but got %r)')
                             % r)
        if "UseUnchanged" in r:
            self.writep.write("UseUnchanged\n")
            self.writep.flush()
            r = self.readp.readline()
Beispiel #58
0
def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
    '''Do the actuall diff:

    - copy to a temp structure if diffing 2 internal revisions
    - copy to a temp structure if diffing working revision with
      another one and more than 1 file is changed
    - just invoke the diff for a single file in the working dir
    '''

    revs = opts.get('rev')
    change = opts.get('change')

    if revs and change:
        msg = _('cannot specify --rev and --change at the same time')
        raise util.Abort(msg)
    elif change:
        node2 = repo.lookup(change)
        node1 = repo[node2].parents()[0].node()
    else:
        node1, node2 = cmdutil.revpair(repo, revs)

    matcher = cmdutil.match(repo, pats, opts)
    modified, added, removed = repo.status(node1, node2, matcher)[:3]
    if not (modified or added or removed):
        return 0

    tmproot = tempfile.mkdtemp(prefix='extdiff.')
    dir2root = ''
    try:
        # Always make a copy of node1
        dir1 = snapshot(ui, repo, modified + removed, node1, tmproot)[0]
        changes = len(modified) + len(removed) + len(added)

        # If node2 in not the wc or there is >1 change, copy it
        if node2 or changes > 1:
            dir2, fns_and_mtime = snapshot(ui, repo, modified + added, node2,
                                           tmproot)
        else:
            # This lets the diff tool open the changed file directly
            dir2 = ''
            dir2root = repo.root
            fns_and_mtime = []

        # If only one change, diff the files instead of the directories
        if changes == 1:
            if len(modified):
                dir1 = os.path.join(dir1, util.localpath(modified[0]))
                dir2 = os.path.join(dir2root, dir2,
                                    util.localpath(modified[0]))
            elif len(removed):
                dir1 = os.path.join(dir1, util.localpath(removed[0]))
                dir2 = os.devnull
            else:
                dir1 = os.devnull
                dir2 = os.path.join(dir2root, dir2, util.localpath(added[0]))

        cmdline = ('%s %s %s %s' %
                   (util.shellquote(diffcmd), ' '.join(diffopts),
                    util.shellquote(dir1), util.shellquote(dir2)))
        ui.debug(_('running %r in %s\n') % (cmdline, tmproot))
        util.system(cmdline, cwd=tmproot)

        for copy_fn, working_fn, mtime in fns_and_mtime:
            if os.path.getmtime(copy_fn) != mtime:
                ui.debug(
                    _('file changed while diffing. '
                      'Overwriting: %s (src: %s)\n') % (working_fn, copy_fn))
                util.copyfile(copy_fn, working_fn)

        return 1
    finally:
        ui.note(_('cleaning up temp directory\n'))
        shutil.rmtree(tmproot)
Beispiel #59
0
def dodiff(ui, repo, diffcmd, diffopts, pats, opts):
    '''Do the actuall diff:

    - copy to a temp structure if diffing 2 internal revisions
    - copy to a temp structure if diffing working revision with
      another one and more than 1 file is changed
    - just invoke the diff for a single file in the working dir
    '''

    revs = opts.get('rev')
    change = opts.get('change')
    args = ' '.join(diffopts)
    do3way = '$parent2' in args

    if revs and change:
        msg = _('cannot specify --rev and --change at the same time')
        raise util.Abort(msg)
    elif change:
        node2 = repo.lookup(change)
        node1a, node1b = repo.changelog.parents(node2)
    else:
        node1a, node2 = cmdutil.revpair(repo, revs)
        if not revs:
            node1b = repo.dirstate.parents()[1]
        else:
            node1b = nullid

    # Disable 3-way merge if there is only one parent
    if do3way:
        if node1b == nullid:
            do3way = False

    matcher = cmdutil.match(repo, pats, opts)
    mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3])
    if do3way:
        mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher)[:3])
    else:
        mod_b, add_b, rem_b = set(), set(), set()
    modadd = mod_a | add_a | mod_b | add_b
    common = modadd | rem_a | rem_b
    if not common:
        return 0

    tmproot = tempfile.mkdtemp(prefix='extdiff.')
    try:
        # Always make a copy of node1a (and node1b, if applicable)
        dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
        dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0]
        if do3way:
            dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
            dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot)[0]
        else:
            dir1b = None

        fns_and_mtime = []

        # If node2 in not the wc or there is >1 change, copy it
        dir2root = ''
        if node2:
            dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0]
        elif len(common) > 1:
            #we only actually need to get the files to copy back to
            #the working dir in this case (because the other cases
            #are: diffing 2 revisions or single file -- in which case
            #the file is already directly passed to the diff tool).
            dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot)
        else:
            # This lets the diff tool open the changed file directly
            dir2 = ''
            dir2root = repo.root

        # If only one change, diff the files instead of the directories
        # Handle bogus modifies correctly by checking if the files exist
        if len(common) == 1:
            common_file = util.localpath(common.pop())
            dir1a = os.path.join(dir1a, common_file)
            if not os.path.isfile(os.path.join(tmproot, dir1a)):
                dir1a = os.devnull
            if do3way:
                dir1b = os.path.join(dir1b, common_file)
                if not os.path.isfile(os.path.join(tmproot, dir1b)):
                    dir1b = os.devnull
            dir2 = os.path.join(dir2root, dir2, common_file)

        # Function to quote file/dir names in the argument string.
        # When not operating in 3-way mode, an empty string is
        # returned for parent2
        replace = dict(parent=dir1a, parent1=dir1a, parent2=dir1b, child=dir2)

        def quote(match):
            key = match.group()[1:]
            if not do3way and key == 'parent2':
                return ''
            return util.shellquote(replace[key])

        # Match parent2 first, so 'parent1?' will match both parent1 and parent
        regex = '\$(parent2|parent1?|child)'
        if not do3way and not re.search(regex, args):
            args += ' $parent1 $child'
        args = re.sub(regex, quote, args)
        cmdline = util.shellquote(diffcmd) + ' ' + args

        ui.debug('running %r in %s\n' % (cmdline, tmproot))
        util.system(cmdline, cwd=tmproot)

        for copy_fn, working_fn, mtime in fns_and_mtime:
            if os.path.getmtime(copy_fn) != mtime:
                ui.debug('file changed while diffing. '
                         'Overwriting: %s (src: %s)\n' % (working_fn, copy_fn))
                util.copyfile(copy_fn, working_fn)

        return 1
    finally:
        ui.note(_('cleaning up temp directory\n'))
        shutil.rmtree(tmproot)