def link(self, args):
        """
        Actually deploy the configuration by linking the correct spot to the original file.
        @param args: The parsed arguments from the command-line.
        """
        if args.dry:
            print(str(self.source) + " -> " + str(self.destination))
            return

        if not self.src_exists:
            return

        if self.dst_exists_before:
            if args.replace:
                if self.dst_is_link_before:
                    util.unlink(self.destination)
                elif self.dst_is_file_before:
                    util.remove(self.destination)
                elif self.dst_is_dir_before:
                    util.remove_dir(self.destination)
                else:
                    #SUS should never get here.
                    raise Exception("WTF is this shit")
            else:
                # File already exists and isn't going to be replaced.
                return
        else:
            #This is some weird nonsense conserning broken links
            if self.dst_is_link_before:
                util.unlink(self.destination)

        if args.copy:
            util.copy(self.source, self.destination)
        else:
            util.link(self.source, self.destination)
Example #2
0
    def testlock(self):
        """return id of locker if lock is valid, else None.

        If old-style lock, we cannot tell what machine locker is on.
        with new-style lock, if locker is on this machine, we can
        see if locker is alive.  If locker is on this machine but
        not alive, we can safely break lock.

        The lock file is only deleted when None is returned.

        """
        locker = util.readlock(self.f)
        try:
            host, pid = locker.split(":", 1)
        except ValueError:
            return locker
        if host != lock._host:
            return locker
        try:
            pid = int(pid)
        except ValueError:
            return locker
        if util.testpid(pid):
            return locker
        # if locker dead, break lock.  must do this with another lock
        # held, or can race and break valid lock.
        try:
            l = lock(self.f + '.break', timeout=0)
            util.unlink(self.f)
            l.release()
        except error.LockError:
            return locker
Example #3
0
    def testlock(self):
        """return id of locker if lock is valid, else None.

        If old-style lock, we cannot tell what machine locker is on.
        with new-style lock, if locker is on this machine, we can
        see if locker is alive.  If locker is on this machine but
        not alive, we can safely break lock.

        The lock file is only deleted when None is returned.

        """
        locker = util.readlock(self.f)
        try:
            host, pid = locker.split(":", 1)
        except ValueError:
            return locker
        if host != lock._host:
            return locker
        try:
            pid = int(pid)
        except ValueError:
            return locker
        if util.testpid(pid):
            return locker
        # if locker dead, break lock.  must do this with another lock
        # held, or can race and break valid lock.
        try:
            l = lock(self.f + '.break', timeout=0)
            util.unlink(self.f)
            l.release()
        except error.LockError:
            return locker
Example #4
0
    def upgrade(self, version, force = False):
        if not mkdir(self.path):
                return version

        if self.updater == "bukkitdev":
            uver, urlh = self.__bukkitdev_info()
        elif self.updater == "bukkitdl":
            uver, urlh = self.__bukkitdl_info()
        elif self.updater == "github":
            uver, urlh = self.__github_info()
        elif self.updater == "jenkins":
            uver, urlh = self.__jenkins_info()
        else:
            log.error("%s: package upgrade failed: invalid updater `%s'",
                      self.package, self.updater)

            return version

        if not urlh:
            log.error("%s: package upgrade failed", self.package)
            return version

        out = os.path.join(self.path, "%s.%s" % (self.package, self.type))

        if uver and uver == version and not force:
            log.info("%s: package already up-to-date", self.package)
            return version

        if not self.dryrun and not download(urlh, out):
            return version

        log.info("%s: package upgraded: %s -> %s", self.package, version, uver)

        if self.dryrun or (self.type != "zip"):
            return uver

        if len(self.extract) < 1:
            return uver

        zf = ZipFile(out, "r")
        nl = zf.namelist()

        for path in self.extract:
            if not path.endswith("/") and path in nl:
                zf.extract(path, self.path)
                continue

            for zpath in nl:
                if zpath.endswith("/"):
                    continue

                if not zpath.startswith(path):
                    continue

                zf.extract(zpath, self.path)

        zf.close()
        unlink(out)

        return uver
Example #5
0
    def kill(server):
        log.info("%s: fake server stopping...", server)

        pidfile = FakeServer.pidfile(server)
        fp      = util.fopen(pidfile, "r")

        if not fp:
            return False

        try:
            pid = int(fp.read())
        except:
            pid = 0

        fp.close()
        util.unlink(pidfile)

        if not pid:
            return False

        try:
            os.kill(pid, SIGINT)
        except Exception, msg:
            log.error("Failed to kill process (%d): %s", pid, msg)
            return False
 def remove(self, list, unlink=False):
     if unlink:
         for f in list:
             try:
                 util.unlink(self._repo.wjoin(f))
             except OSError, inst:
                 if inst.errno != errno.ENOENT:
                     raise
Example #7
0
 def remove(self, list, unlink=False):
     if unlink:
         for f in list:
             try:
                 util.unlink(self._repo.wjoin(f))
             except OSError, inst:
                 if inst.errno != errno.ENOENT:
                     raise
Example #8
0
def applyupdates(repo, action, wctx, mctx):
    "apply the merge action list to the working directory"

    updated, merged, removed, unresolved = 0, 0, 0, 0
    ms = mergestate(repo)
    ms.reset(wctx.parents()[0].node())
    moves = []
    action.sort(actioncmp)

    # prescan for merges
    for a in action:
        f, m = a[:2]
        if m == 'm': # merge
            f2, fd, flags, move = a[2:]
            repo.ui.debug(_("preserving %s for resolve of %s\n") % (f, fd))
            fcl = wctx[f]
            fco = mctx[f2]
            fca = fcl.ancestor(fco) or repo.filectx(f, fileid=nullrev)
            ms.add(fcl, fco, fca, fd, flags)
            if f != fd and move:
                moves.append(f)

    # remove renamed files after safely stored
    for f in moves:
        if util.lexists(repo.wjoin(f)):
            repo.ui.debug(_("removing %s\n") % f)
            os.unlink(repo.wjoin(f))

    audit_path = util.path_auditor(repo.root)

    for a in action:
        f, m = a[:2]
        if f and f[0] == "/":
            continue
        if m == "r": # remove
            repo.ui.note(_("removing %s\n") % f)
            audit_path(f)
            try:
                util.unlink(repo.wjoin(f))
            except OSError, inst:
                if inst.errno != errno.ENOENT:
                    repo.ui.warn(_("update failed to remove %s: %s!\n") %
                                 (f, inst.strerror))
            removed += 1
        elif m == "m": # merge
            f2, fd, flags, move = a[2:]
            r = ms.resolve(fd, wctx, mctx)
            if r > 0:
                unresolved += 1
            else:
                if r is None:
                    updated += 1
                else:
                    merged += 1
            util.set_flags(repo.wjoin(fd), 'l' in flags, 'x' in flags)
            if f != fd and move and util.lexists(repo.wjoin(f)):
                repo.ui.debug(_("removing %s\n") % f)
                os.unlink(repo.wjoin(f))
Example #9
0
 def test_raise_exceptions(self):
     """Test that exceptions raised by a task are propagated"""
     m = util.Manager()
     m.add_slave(IMP.parallel.LocalSlave())
     c = m.get_context()
     c.add_task(tasks.error_task)
     self.assertRaises(IMP.parallel.RemoteError, list,
                       c.get_results_unordered())
     util.unlink("slave0.output")
Example #10
0
 def test_pass_exceptions(self):
     """Test that exceptions can be passed to and from tasks"""
     m = util.Manager()
     m.add_slave(IMP.parallel.LocalSlave())
     c = m.get_context()
     c.add_task(tasks.SimpleTask(IndexError("test")))
     results = list(c.get_results_unordered())
     self.assertIsInstance(results[0], IndexError)
     util.unlink("slave0.output")
Example #11
0
    def __call__(self,
                 path,
                 mode="r",
                 text=False,
                 atomictemp=False,
                 notindexed=False):
        '''Open ``path`` file, which is relative to vfs root.

        Newly created directories are marked as "not to be indexed by
        the content indexing service", if ``notindexed`` is specified
        for "write" mode access.
        '''
        if self._audit:
            r = util.checkosfilename(path)
            if r:
                raise util.Abort("%s: %r" % (r, path))
        self.audit(path)
        f = self.join(path)

        if not text and "b" not in mode:
            mode += "b"  # for that other OS

        nlink = -1
        if mode not in ('r', 'rb'):
            dirname, basename = util.split(f)
            # If basename is empty, then the path is malformed because it points
            # to a directory. Let the posixfile() call below raise IOError.
            if basename:
                if atomictemp:
                    util.ensuredirs(dirname, self.createmode, notindexed)
                    return util.atomictempfile(f, mode, self.createmode)
                try:
                    if 'w' in mode:
                        util.unlink(f)
                        nlink = 0
                    else:
                        # nlinks() may behave differently for files on Windows
                        # shares if the file is open.
                        fd = util.posixfile(f)
                        nlink = util.nlinks(f)
                        if nlink < 1:
                            nlink = 2  # force mktempcopy (issue1922)
                        fd.close()
                except (OSError, IOError) as e:
                    if e.errno != errno.ENOENT:
                        raise
                    nlink = 0
                    util.ensuredirs(dirname, self.createmode, notindexed)
                if nlink > 0:
                    if self._trustnlink is None:
                        self._trustnlink = nlink > 1 or util.checknlink(f)
                    if nlink > 1 or not self._trustnlink:
                        util.rename(util.mktempcopy(f), f)
        fp = util.posixfile(f, mode)
        if nlink == 0:
            self._fixfilemode(f)
        return fp
Example #12
0
 def test_startup(self):
     """Test context startup callable"""
     m = util.Manager(output='startup%d.out')
     m.add_slave(IMP.parallel.LocalSlave())
     c = m.get_context(startup=tasks.SimpleTask(("foo", "bar")))
     c.add_task(tasks.simple_func)
     c.add_task(tasks.simple_func)
     results = list(c.get_results_unordered())
     self.assertEqual(results, [('foo', 'bar'), ('foo', 'bar')])
     util.unlink("startup0.out")
Example #13
0
 def release(self):
     if self.held > 1:
         self.held -= 1
     elif self.held == 1:
         self.held = 0
         if self.releasefn:
             self.releasefn()
         try:
             util.unlink(self.f)
         except OSError:
             pass
Example #14
0
 def release(self):
     if self.held > 1:
         self.held -= 1
     elif self.held == 1:
         self.held = 0
         if self.releasefn:
             self.releasefn()
         try:
             util.unlink(self.f)
         except OSError:
             pass
Example #15
0
 def test_simple(self):
     """Test that slave tasks can start up and communicate"""
     m = util.Manager(output='simple%d.out')
     m.add_slave(IMP.parallel.LocalSlave())
     c = m.get_context()
     for i in range(10):
         c.add_task(tasks.SimpleTask(i))
     results = list(c.get_results_unordered())
     results.sort()
     self.assertEqual(results, list(range(10)))
     util.unlink("simple0.out")
Example #16
0
 def close(self):
     '''commit the transaction'''
     self.count -= 1
     if self.count != 0:
         return
     self.file.close()
     self.entries = []
     if self.after:
         self.after()
     if os.path.isfile(self.journal):
         util.unlink(self.journal)
     self.journal = None
Example #17
0
 def test_startup_heartbeat(self):
     """Make sure that startup failures cause a timeout"""
     def empty_task():
         pass
     m = util.Manager(python="/path/does/not/exist")
     m.heartbeat_timeout = 0.1
     m.add_slave(IMP.parallel.LocalSlave())
     c = m.get_context()
     c.add_task(empty_task)
     self.assertRaises(IMP.parallel.NetworkError, list,
                       c.get_results_unordered())
     util.unlink('slave0.output')
 def close(self):
     '''commit the transaction'''
     self.count -= 1
     if self.count != 0:
         return
     self.file.close()
     self.entries = []
     if self.after:
         self.after()
     if os.path.isfile(self.journal):
         util.unlink(self.journal)
     self.journal = None
Example #19
0
    def __call__(self, path, mode="r", text=False, atomictemp=False,
                 notindexed=False):
        '''Open ``path`` file, which is relative to vfs root.

        Newly created directories are marked as "not to be indexed by
        the content indexing service", if ``notindexed`` is specified
        for "write" mode access.
        '''
        if self._audit:
            r = util.checkosfilename(path)
            if r:
                raise util.Abort("%s: %r" % (r, path))
        self.audit(path)
        f = self.join(path)

        if not text and "b" not in mode:
            mode += "b" # for that other OS

        nlink = -1
        if mode not in ('r', 'rb'):
            dirname, basename = util.split(f)
            # If basename is empty, then the path is malformed because it points
            # to a directory. Let the posixfile() call below raise IOError.
            if basename:
                if atomictemp:
                    util.ensuredirs(dirname, self.createmode, notindexed)
                    return util.atomictempfile(f, mode, self.createmode)
                try:
                    if 'w' in mode:
                        util.unlink(f)
                        nlink = 0
                    else:
                        # nlinks() may behave differently for files on Windows
                        # shares if the file is open.
                        fd = util.posixfile(f)
                        nlink = util.nlinks(f)
                        if nlink < 1:
                            nlink = 2 # force mktempcopy (issue1922)
                        fd.close()
                except (OSError, IOError) as e:
                    if e.errno != errno.ENOENT:
                        raise
                    nlink = 0
                    util.ensuredirs(dirname, self.createmode, notindexed)
                if nlink > 0:
                    if self._trustnlink is None:
                        self._trustnlink = nlink > 1 or util.checknlink(f)
                    if nlink > 1 or not self._trustnlink:
                        util.rename(util.mktempcopy(f), f)
        fp = util.posixfile(f, mode)
        if nlink == 0:
            self._fixfilemode(f)
        return fp
Example #20
0
    def release(self):
        """release the lock and execute callback function if any

        If the lock have been aquired multiple time, the actual release is
        delayed to the last relase call."""
        if self.held > 1:
            self.held -= 1
        elif self.held == 1:
            self.held = 0
            if self.releasefn:
                self.releasefn()
            try:
                util.unlink(self.f)
            except OSError:
                pass
            for callback in self.postrelease:
                callback()
Example #21
0
def applyupdates(repo, action, wctx, mctx):
    "apply the merge action list to the working directory"

    updated, merged, removed, unresolved = 0, 0, 0, 0
    action.sort()
    # prescan for copy/renames
    for a in action:
        f, m = a[:2]
        if m == 'm':  # merge
            f2, fd, flags, move = a[2:]
            if f != fd:
                repo.ui.debug(_("copying %s to %s\n") % (f, fd))
                repo.wwrite(fd, repo.wread(f), flags)

    audit_path = util.path_auditor(repo.root)

    for a in action:
        f, m = a[:2]
        if f and f[0] == "/":
            continue
        if m == "r":  # remove
            repo.ui.note(_("removing %s\n") % f)
            audit_path(f)
            try:
                util.unlink(repo.wjoin(f))
            except OSError, inst:
                if inst.errno != errno.ENOENT:
                    repo.ui.warn(
                        _("update failed to remove %s: %s!\n") %
                        (f, inst.strerror))
            removed += 1
        elif m == "m":  # merge
            f2, fd, flags, move = a[2:]
            r = filemerge(repo, f, fd, f2, wctx, mctx)
            if r > 0:
                unresolved += 1
            else:
                if r is None:
                    updated += 1
                else:
                    merged += 1
            util.set_exec(repo.wjoin(fd), "x" in flags)
            if f != fd and move and util.lexists(repo.wjoin(f)):
                repo.ui.debug(_("removing %s\n") % f)
                os.unlink(repo.wjoin(f))
Example #22
0
def applyupdates(repo, action, wctx, mctx):
    "apply the merge action list to the working directory"

    updated, merged, removed, unresolved = 0, 0, 0, 0
    action.sort()
    # prescan for copy/renames
    for a in action:
        f, m = a[:2]
        if m == 'm': # merge
            f2, fd, flags, move = a[2:]
            if f != fd:
                repo.ui.debug(_("copying %s to %s\n") % (f, fd))
                repo.wwrite(fd, repo.wread(f), flags)

    audit_path = util.path_auditor(repo.root)

    for a in action:
        f, m = a[:2]
        if f and f[0] == "/":
            continue
        if m == "r": # remove
            repo.ui.note(_("removing %s\n") % f)
            audit_path(f)
            try:
                util.unlink(repo.wjoin(f))
            except OSError, inst:
                if inst.errno != errno.ENOENT:
                    repo.ui.warn(_("update failed to remove %s: %s!\n") %
                                 (f, inst.strerror))
            removed += 1
        elif m == "m": # merge
            f2, fd, flags, move = a[2:]
            r = filemerge.filemerge(repo, f, fd, f2, wctx, mctx)
            if r > 0:
                unresolved += 1
            else:
                if r is None:
                    updated += 1
                else:
                    merged += 1
            util.set_flags(repo.wjoin(fd), 'l' in flags, 'x' in flags)
            if f != fd and move and util.lexists(repo.wjoin(f)):
                repo.ui.debug(_("removing %s\n") % f)
                os.unlink(repo.wjoin(f))
Example #23
0
    def __call__(self, path, mode="r", text=False, atomictemp=False):
        if self._audit:
            r = util.checkosfilename(path)
            if r:
                raise util.Abort("%s: %r" % (r, path))
        self.auditor(path)
        f = self.join(path)

        if not text and "b" not in mode:
            mode += "b"  # for that other OS

        nlink = -1
        dirname, basename = os.path.split(f)
        # If basename is empty, then the path is malformed because it points
        # to a directory. Let the posixfile() call below raise IOError.
        if basename and mode not in ('r', 'rb'):
            if atomictemp:
                if not os.path.isdir(dirname):
                    util.makedirs(dirname, self.createmode)
                return util.atomictempfile(f, mode, self.createmode)
            try:
                if 'w' in mode:
                    util.unlink(f)
                    nlink = 0
                else:
                    # nlinks() may behave differently for files on Windows
                    # shares if the file is open.
                    fd = util.posixfile(f)
                    nlink = util.nlinks(f)
                    if nlink < 1:
                        nlink = 2  # force mktempcopy (issue1922)
                    fd.close()
            except (OSError, IOError), e:
                if e.errno != errno.ENOENT:
                    raise
                nlink = 0
                if not os.path.isdir(dirname):
                    util.makedirs(dirname, self.createmode)
            if nlink > 0:
                if self._trustnlink is None:
                    self._trustnlink = nlink > 1 or util.checknlink(f)
                if nlink > 1 or not self._trustnlink:
                    util.rename(util.mktempcopy(f), f)
Example #24
0
    def __call__(self, path, mode="r", text=False, atomictemp=False):
        if self._audit:
            r = util.checkosfilename(path)
            if r:
                raise util.Abort("%s: %r" % (r, path))
        self.auditor(path)
        f = os.path.join(self.base, path)

        if not text and "b" not in mode:
            mode += "b" # for that other OS

        nlink = -1
        dirname, basename = os.path.split(f)
        # If basename is empty, then the path is malformed because it points
        # to a directory. Let the posixfile() call below raise IOError.
        if basename and mode not in ('r', 'rb'):
            if atomictemp:
                if not os.path.isdir(dirname):
                    util.makedirs(dirname, self.createmode)
                return util.atomictempfile(f, mode, self.createmode)
            try:
                if 'w' in mode:
                    util.unlink(f)
                    nlink = 0
                else:
                    # nlinks() may behave differently for files on Windows
                    # shares if the file is open.
                    fd = util.posixfile(f)
                    nlink = util.nlinks(f)
                    if nlink < 1:
                        nlink = 2 # force mktempcopy (issue1922)
                    fd.close()
            except (OSError, IOError), e:
                if e.errno != errno.ENOENT:
                    raise
                nlink = 0
                if not os.path.isdir(dirname):
                    util.makedirs(dirname, self.createmode)
            if nlink > 0:
                if self._trustnlink is None:
                    self._trustnlink = nlink > 1 or util.checknlink(f)
                if nlink > 1 or not self._trustnlink:
                    util.rename(util.mktempcopy(f), f)
Example #25
0
def _playback(journal, report, opener, entries, unlink=True):
    for f, o, ignore in entries:
        if o or not unlink:
            try:
                fp = opener(f, 'a')
                fp.truncate(o)
                fp.close()
            except IOError:
                report(_("failed to truncate %s\n") % f)
                raise
        else:
            try:
                fp = opener(f)
                fn = fp.name
                fp.close()
                util.unlink(fn)
            except (IOError, OSError), inst:
                if inst.errno != errno.ENOENT:
                    raise
def _playback(journal, report, opener, entries, unlink=True):
    for f, o, ignore in entries:
        if o or not unlink:
            try:
                fp = opener(f, 'a')
                fp.truncate(o)
                fp.close()
            except IOError:
                report(_("failed to truncate %s\n") % f)
                raise
        else:
            try:
                fp = opener(f)
                fn = fp.name
                fp.close()
                util.unlink(fn)
            except (IOError, OSError), inst:
                if inst.errno != errno.ENOENT:
                    raise
Example #27
0
    def release(self):
        """release the lock and execute callback function if any

        If the lock has been acquired multiple times, the actual release is
        delayed to the last release call."""
        if self.held > 1:
            self.held -= 1
        elif self.held == 1:
            self.held = 0
            if os.getpid() != self.pid:
                # we forked, and are not the parent
                return
            if self.releasefn:
                self.releasefn()
            try:
                util.unlink(self.f)
            except OSError:
                pass
            for callback in self.postrelease:
                callback()
Example #28
0
    def _abort(self):
        self.count = 0
        self.usages = 0
        self.file.close()

        try:
            if not self.entries:
                if self.journal:
                    util.unlink(self.journal)
                return

            self.report(_("transaction abort!\n"))

            try:
                _playback(self.journal, self.report, self.opener, self.entries,
                          False)
                self.report(_("rollback completed\n"))
            except:
                self.report(_("rollback failed - please run hg recover\n"))
        finally:
            self.journal = None
Example #29
0
    def test_floats(self):
        """Check that NaN and Inf floats are pickled correctly"""
        if sys.platform in ('irix6', 'osf1V5'):
            self.skipTest("Cannot reliably handle NaN and Inf on Irix or Alpha")

        m = util.Manager()
        m.add_slave(IMP.parallel.LocalSlave())
        c = m.get_context()

        try:
            inf = float('inf')
            nan = float('nan')
        except ValueError:
            # Python 2.5 on Windows reports 'invalid literal', so use another
            # method to get inf and nan:
            inf = 1e300 * 1e300
            nan = inf - inf
        for f in (inf, nan):
            c.add_task(tasks.SimpleTask(f))
        results = list(c.get_results_unordered())
        util.unlink("slave0.output")
    def _abort(self):
        self.count = 0
        self.usages = 0
        self.file.close()

        try:
            if not self.entries:
                if self.journal:
                    util.unlink(self.journal)
                return

            self.report(_("transaction abort!\n"))

            try:
                _playback(self.journal, self.report, self.opener,
                          self.entries, False)
                self.report(_("rollback completed\n"))
            except Exception:
                self.report(_("rollback failed - please run hg recover\n"))
        finally:
            self.journal = None
Example #31
0
def update(repo,
           node,
           branchmerge,
           force,
           partial,
           ancestor=None,
           mergeancestor=False,
           labels=None):
    """
    Perform a merge between the working directory and the given node

    node = the node to update to, or None if unspecified
    branchmerge = whether to merge between branches
    force = whether to force branch merging or file overwriting
    partial = a function to filter file lists (dirstate not updated)
    mergeancestor = whether it is merging with an ancestor. If true,
      we should accept the incoming changes for any prompts that occur.
      If false, merging with an ancestor (fast-forward) is only allowed
      between different named branches. This flag is used by rebase extension
      as a temporary fix and should be avoided in general.

    The table below shows all the behaviors of the update command
    given the -c and -C or no options, whether the working directory
    is dirty, whether a revision is specified, and the relationship of
    the parent rev to the target rev (linear, on the same named
    branch, or on another named branch).

    This logic is tested by test-update-branches.t.

    -c  -C  dirty  rev  |  linear   same  cross
     n   n    n     n   |    ok     (1)     x
     n   n    n     y   |    ok     ok     ok
     n   n    y     n   |   merge   (2)    (2)
     n   n    y     y   |   merge   (3)    (3)
     n   y    *     *   |    ---  discard  ---
     y   n    y     *   |    ---    (4)    ---
     y   n    n     *   |    ---    ok     ---
     y   y    *     *   |    ---    (5)    ---

    x = can't happen
    * = don't-care
    1 = abort: not a linear update (merge or update --check to force update)
    2 = abort: uncommitted changes (commit and merge, or update --clean to
                 discard changes)
    3 = abort: uncommitted changes (commit or update --clean to discard changes)
    4 = abort: uncommitted changes (checked in commands.py)
    5 = incompatible options (checked in commands.py)

    Return the same tuple as applyupdates().
    """

    onode = node
    wlock = repo.wlock()
    try:
        wc = repo[None]
        pl = wc.parents()
        p1 = pl[0]
        pas = [None]
        if ancestor:
            pas = [repo[ancestor]]

        if node is None:
            # Here is where we should consider bookmarks, divergent bookmarks,
            # foreground changesets (successors), and tip of current branch;
            # but currently we are only checking the branch tips.
            try:
                node = repo.branchtip(wc.branch())
            except errormod.RepoLookupError:
                if wc.branch() == "default":  # no default branch!
                    node = repo.lookup("tip")  # update to tip
                else:
                    raise util.Abort(_("branch %s not found") % wc.branch())

            if p1.obsolete() and not p1.children():
                # allow updating to successors
                successors = obsolete.successorssets(repo, p1.node())

                # behavior of certain cases is as follows,
                #
                # divergent changesets: update to highest rev, similar to what
                #     is currently done when there are more than one head
                #     (i.e. 'tip')
                #
                # replaced changesets: same as divergent except we know there
                # is no conflict
                #
                # pruned changeset: no update is done; though, we could
                #     consider updating to the first non-obsolete parent,
                #     similar to what is current done for 'hg prune'

                if successors:
                    # flatten the list here handles both divergent (len > 1)
                    # and the usual case (len = 1)
                    successors = [n for sub in successors for n in sub]

                    # get the max revision for the given successors set,
                    # i.e. the 'tip' of a set
                    node = repo.revs("max(%ln)", successors).first()
                    pas = [p1]

        overwrite = force and not branchmerge

        p2 = repo[node]
        if pas[0] is None:
            if repo.ui.config("merge", "preferancestor", '*') == '*':
                cahs = repo.changelog.commonancestorsheads(
                    p1.node(), p2.node())
                pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
            else:
                pas = [p1.ancestor(p2, warn=branchmerge)]

        fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)

        ### check phase
        if not overwrite and len(pl) > 1:
            raise util.Abort(_("outstanding uncommitted merge"))
        if branchmerge:
            if pas == [p2]:
                raise util.Abort(
                    _("merging with a working directory ancestor"
                      " has no effect"))
            elif pas == [p1]:
                if not mergeancestor and p1.branch() == p2.branch():
                    raise util.Abort(_("nothing to merge"),
                                     hint=_("use 'hg update' "
                                            "or check 'hg heads'"))
            if not force and (wc.files() or wc.deleted()):
                raise util.Abort(_("uncommitted changes"),
                                 hint=_("use 'hg status' to list changes"))
            for s in sorted(wc.substate):
                if wc.sub(s).dirty():
                    raise util.Abort(
                        _("uncommitted changes in "
                          "subrepository '%s'") % s)

        elif not overwrite:
            if p1 == p2:  # no-op update
                # call the hooks and exit early
                repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
                repo.hook('update', parent1=xp2, parent2='', error=0)
                return 0, 0, 0, 0

            if pas not in ([p1], [p2]):  # nonlinear
                dirty = wc.dirty(missing=True)
                if dirty or onode is None:
                    # Branching is a bit strange to ensure we do the minimal
                    # amount of call to obsolete.background.
                    foreground = obsolete.foreground(repo, [p1.node()])
                    # note: the <node> variable contains a random identifier
                    if repo[node].node() in foreground:
                        pas = [p1]  # allow updating to successors
                    elif dirty:
                        msg = _("uncommitted changes")
                        if onode is None:
                            hint = _("commit and merge, or update --clean to"
                                     " discard changes")
                        else:
                            hint = _("commit or update --clean to discard"
                                     " changes")
                        raise util.Abort(msg, hint=hint)
                    else:  # node is none
                        msg = _("not a linear update")
                        hint = _("merge or update --check to force update")
                        raise util.Abort(msg, hint=hint)
                else:
                    # Allow jumping branches if clean and specific rev given
                    pas = [p1]

        followcopies = False
        if overwrite:
            pas = [wc]
        elif pas == [p2]:  # backwards
            pas = [wc.p1()]
        elif not branchmerge and not wc.dirty(missing=True):
            pass
        elif pas[0] and repo.ui.configbool("merge", "followcopies", True):
            followcopies = True

        ### calculate phase
        actions = calculateupdates(repo, wc, p2, pas, branchmerge, force,
                                   partial, mergeancestor, followcopies)

        ### apply phase
        if not branchmerge:  # just jump to the new rev
            fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
        if not partial:
            repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
            # note that we're in the middle of an update
            repo.vfs.write('updatestate', p2.hex())

        stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)

        if not partial:
            repo.dirstate.beginparentchange()
            repo.setparents(fp1, fp2)
            recordupdates(repo, actions, branchmerge)
            # update completed, clear state
            util.unlink(repo.join('updatestate'))

            if not branchmerge:
                repo.dirstate.setbranch(p2.branch())
            repo.dirstate.endparentchange()
    finally:
        wlock.release()

    if not partial:
        repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
    return stats
Example #32
0
def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None):
    """perform a 3-way merge in the working directory

    mynode = parent node before merge
    orig = original local filename before merge
    fco = other file context
    fca = ancestor file context
    fcd = local file context for current/destination file
    """
    def temp(prefix, ctx):
        pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
        (fd, name) = tempfile.mkstemp(prefix=pre)
        data = repo.wwritedata(ctx.path(), ctx.data())
        f = os.fdopen(fd, "wb")
        f.write(data)
        f.close()
        return name

    if not fco.cmp(fcd):  # files identical?
        return None

    ui = repo.ui
    fd = fcd.path()
    binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
    symlink = 'l' in fcd.flags() + fco.flags()
    tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
    ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
             (tool, fd, binary, symlink))

    if tool in internals:
        func = internals[tool]
        trymerge = func.trymerge
        onfailure = func.onfailure
    else:
        func = _xmerge
        trymerge = True
        onfailure = _("merging %s failed!\n")

    toolconf = tool, toolpath, binary, symlink

    if not trymerge:
        return func(repo, mynode, orig, fcd, fco, fca, toolconf)

    a = repo.wjoin(fd)
    b = temp("base", fca)
    c = temp("other", fco)
    back = a + ".orig"
    util.copyfile(a, back)

    if orig != fco.path():
        ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
    else:
        ui.status(_("merging %s\n") % fd)

    ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))

    markerstyle = ui.config('ui', 'mergemarkers', 'basic')
    if not labels:
        labels = _defaultconflictlabels
    if markerstyle != 'basic':
        labels = _formatlabels(repo, fcd, fco, fca, labels)

    needcheck, r = func(repo,
                        mynode,
                        orig,
                        fcd,
                        fco,
                        fca,
                        toolconf, (a, b, c, back),
                        labels=labels)
    if not needcheck:
        if r:
            if onfailure:
                ui.warn(onfailure % fd)
        else:
            util.unlink(back)

        util.unlink(b)
        util.unlink(c)
        return r

    if not r and (_toolbool(ui, tool, "checkconflicts")
                  or 'conflicts' in _toollist(ui, tool, "check")):
        if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
                     re.MULTILINE):
            r = 1

    checked = False
    if 'prompt' in _toollist(ui, tool, "check"):
        checked = True
        if ui.promptchoice(
                _("was merge of '%s' successful (yn)?"
                  "$$ &Yes $$ &No") % fd, 1):
            r = 1

    if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
                                  'changed' in _toollist(ui, tool, "check")):
        if filecmp.cmp(a, back):
            if ui.promptchoice(
                    _(" output file %s appears unchanged\n"
                      "was merge successful (yn)?"
                      "$$ &Yes $$ &No") % fd, 1):
                r = 1

    if _toolbool(ui, tool, "fixeol"):
        _matcheol(a, back)

    if r:
        if onfailure:
            ui.warn(onfailure % fd)
    else:
        util.unlink(back)

    util.unlink(b)
    util.unlink(c)
    return r
Example #33
0
 def unlink(self, path=None):
     return util.unlink(self.join(path))
Example #34
0
def applyupdates(repo, action, wctx, mctx):
    "apply the merge action list to the working directory"

    updated, merged, removed, unresolved = 0, 0, 0, 0
    ms = mergestate(repo)
    ms.reset(wctx.parents()[0].node())
    moves = []
    action.sort(key=actionkey)
    substate = wctx.substate  # prime

    # prescan for merges
    for a in action:
        f, m = a[:2]
        if m == 'm':  # merge
            f2, fd, flags, move = a[2:]
            if f == '.hgsubstate':  # merged internally
                continue
            repo.ui.debug(_("preserving %s for resolve of %s\n") % (f, fd))
            fcl = wctx[f]
            fco = mctx[f2]
            fca = fcl.ancestor(fco) or repo.filectx(f, fileid=nullrev)
            ms.add(fcl, fco, fca, fd, flags)
            if f != fd and move:
                moves.append(f)

    # remove renamed files after safely stored
    for f in moves:
        if util.lexists(repo.wjoin(f)):
            repo.ui.debug(_("removing %s\n") % f)
            os.unlink(repo.wjoin(f))

    audit_path = util.path_auditor(repo.root)

    for a in action:
        f, m = a[:2]
        if f and f[0] == "/":
            continue
        if m == "r":  # remove
            repo.ui.note(_("removing %s\n") % f)
            audit_path(f)
            if f == '.hgsubstate':  # subrepo states need updating
                subrepo.submerge(repo, wctx, mctx, wctx)
            try:
                util.unlink(repo.wjoin(f))
            except OSError, inst:
                if inst.errno != errno.ENOENT:
                    repo.ui.warn(
                        _("update failed to remove %s: %s!\n") %
                        (f, inst.strerror))
            removed += 1
        elif m == "m":  # merge
            if f == '.hgsubstate':  # subrepo states need updating
                subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx))
                continue
            f2, fd, flags, move = a[2:]
            r = ms.resolve(fd, wctx, mctx)
            if r is not None and r > 0:
                unresolved += 1
            else:
                if r is None:
                    updated += 1
                else:
                    merged += 1
            util.set_flags(repo.wjoin(fd), 'l' in flags, 'x' in flags)
            if f != fd and move and util.lexists(repo.wjoin(f)):
                repo.ui.debug(_("removing %s\n") % f)
                os.unlink(repo.wjoin(f))
Example #35
0
                os.unlink(repo.wjoin(f))
        elif m == "g":  # get
            flags = a[2]
            repo.ui.note(_("getting %s\n") % f)
            t = mctx.filectx(f).data()
            repo.wwrite(f, t, flags)
            updated += 1
            if f == '.hgsubstate':  # subrepo states need updating
                subrepo.submerge(repo, wctx, mctx, wctx)
        elif m == "d":  # directory rename
            f2, fd, flags = a[2:]
            if f:
                repo.ui.note(_("moving %s to %s\n") % (f, fd))
                t = wctx.filectx(f).data()
                repo.wwrite(fd, t, flags)
                util.unlink(repo.wjoin(f))
            if f2:
                repo.ui.note(_("getting %s to %s\n") % (f2, fd))
                t = mctx.filectx(f2).data()
                repo.wwrite(fd, t, flags)
            updated += 1
        elif m == "dr":  # divergent renames
            fl = a[2]
            repo.ui.warn(
                _("warning: detected divergent renames of %s to:\n") % f)
            for nf in fl:
                repo.ui.warn(" %s\n" % nf)
        elif m == "e":  # exec
            flags = a[2]
            util.set_flags(repo.wjoin(f), 'l' in flags, 'x' in flags)
Example #36
0
def filemerge(repo, mynode, orig, fcd, fco, fca, labels=None):
    """perform a 3-way merge in the working directory

    mynode = parent node before merge
    orig = original local filename before merge
    fco = other file context
    fca = ancestor file context
    fcd = local file context for current/destination file
    """

    def temp(prefix, ctx):
        pre = "%s~%s." % (os.path.basename(ctx.path()), prefix)
        (fd, name) = tempfile.mkstemp(prefix=pre)
        data = repo.wwritedata(ctx.path(), ctx.data())
        f = os.fdopen(fd, "wb")
        f.write(data)
        f.close()
        return name

    if not fco.cmp(fcd): # files identical?
        return None

    ui = repo.ui
    fd = fcd.path()
    binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
    symlink = 'l' in fcd.flags() + fco.flags()
    tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
    ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
               (tool, fd, binary, symlink))

    if tool in internals:
        func = internals[tool]
        trymerge = func.trymerge
        onfailure = func.onfailure
    else:
        func = _xmerge
        trymerge = True
        onfailure = _("merging %s failed!\n")

    toolconf = tool, toolpath, binary, symlink

    if not trymerge:
        return func(repo, mynode, orig, fcd, fco, fca, toolconf)

    a = repo.wjoin(fd)
    b = temp("base", fca)
    c = temp("other", fco)
    back = a + ".orig"
    util.copyfile(a, back)

    if orig != fco.path():
        ui.status(_("merging %s and %s to %s\n") % (orig, fco.path(), fd))
    else:
        ui.status(_("merging %s\n") % fd)

    ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))

    markerstyle = ui.config('ui', 'mergemarkers', 'basic')
    if not labels:
        labels = _defaultconflictlabels
    if markerstyle != 'basic':
        labels = _formatlabels(repo, fcd, fco, fca, labels)

    needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
                        (a, b, c, back), labels=labels)
    if not needcheck:
        if r:
            if onfailure:
                ui.warn(onfailure % fd)
        else:
            util.unlink(back)

        util.unlink(b)
        util.unlink(c)
        return r

    if not r and (_toolbool(ui, tool, "checkconflicts") or
                  'conflicts' in _toollist(ui, tool, "check")):
        if re.search("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data(),
                     re.MULTILINE):
            r = 1

    checked = False
    if 'prompt' in _toollist(ui, tool, "check"):
        checked = True
        if ui.promptchoice(_("was merge of '%s' successful (yn)?"
                             "$$ &Yes $$ &No") % fd, 1):
            r = 1

    if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
                                  'changed' in _toollist(ui, tool, "check")):
        if filecmp.cmp(a, back):
            if ui.promptchoice(_(" output file %s appears unchanged\n"
                                 "was merge successful (yn)?"
                                 "$$ &Yes $$ &No") % fd, 1):
                r = 1

    if _toolbool(ui, tool, "fixeol"):
        _matcheol(a, back)

    if r:
        if onfailure:
            ui.warn(onfailure % fd)
    else:
        util.unlink(back)

    util.unlink(b)
    util.unlink(c)
    return r
Example #37
0
def update(repo, node, branchmerge, force, partial, ancestor=None,
           mergeancestor=False, labels=None):
    """
    Perform a merge between the working directory and the given node

    node = the node to update to, or None if unspecified
    branchmerge = whether to merge between branches
    force = whether to force branch merging or file overwriting
    partial = a function to filter file lists (dirstate not updated)
    mergeancestor = whether it is merging with an ancestor. If true,
      we should accept the incoming changes for any prompts that occur.
      If false, merging with an ancestor (fast-forward) is only allowed
      between different named branches. This flag is used by rebase extension
      as a temporary fix and should be avoided in general.

    The table below shows all the behaviors of the update command
    given the -c and -C or no options, whether the working directory
    is dirty, whether a revision is specified, and the relationship of
    the parent rev to the target rev (linear, on the same named
    branch, or on another named branch).

    This logic is tested by test-update-branches.t.

    -c  -C  dirty  rev  |  linear   same  cross
     n   n    n     n   |    ok     (1)     x
     n   n    n     y   |    ok     ok     ok
     n   n    y     n   |   merge   (2)    (2)
     n   n    y     y   |   merge   (3)    (3)
     n   y    *     *   |    ---  discard  ---
     y   n    y     *   |    ---    (4)    ---
     y   n    n     *   |    ---    ok     ---
     y   y    *     *   |    ---    (5)    ---

    x = can't happen
    * = don't-care
    1 = abort: not a linear update (merge or update --check to force update)
    2 = abort: uncommitted changes (commit and merge, or update --clean to
                 discard changes)
    3 = abort: uncommitted changes (commit or update --clean to discard changes)
    4 = abort: uncommitted changes (checked in commands.py)
    5 = incompatible options (checked in commands.py)

    Return the same tuple as applyupdates().
    """

    onode = node
    wlock = repo.wlock()
    try:
        wc = repo[None]
        pl = wc.parents()
        p1 = pl[0]
        pas = [None]
        if ancestor is not None:
            pas = [repo[ancestor]]

        if node is None:
            # Here is where we should consider bookmarks, divergent bookmarks,
            # foreground changesets (successors), and tip of current branch;
            # but currently we are only checking the branch tips.
            try:
                node = repo.branchtip(wc.branch())
            except errormod.RepoLookupError:
                if wc.branch() == 'default': # no default branch!
                    node = repo.lookup('tip') # update to tip
                else:
                    raise util.Abort(_("branch %s not found") % wc.branch())

            if p1.obsolete() and not p1.children():
                # allow updating to successors
                successors = obsolete.successorssets(repo, p1.node())

                # behavior of certain cases is as follows,
                #
                # divergent changesets: update to highest rev, similar to what
                #     is currently done when there are more than one head
                #     (i.e. 'tip')
                #
                # replaced changesets: same as divergent except we know there
                # is no conflict
                #
                # pruned changeset: no update is done; though, we could
                #     consider updating to the first non-obsolete parent,
                #     similar to what is current done for 'hg prune'

                if successors:
                    # flatten the list here handles both divergent (len > 1)
                    # and the usual case (len = 1)
                    successors = [n for sub in successors for n in sub]

                    # get the max revision for the given successors set,
                    # i.e. the 'tip' of a set
                    node = repo.revs('max(%ln)', successors).first()
                    pas = [p1]

        overwrite = force and not branchmerge

        p2 = repo[node]
        if pas[0] is None:
            if repo.ui.config('merge', 'preferancestor', '*') == '*':
                cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
                pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
            else:
                pas = [p1.ancestor(p2, warn=branchmerge)]

        fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)

        ### check phase
        if not overwrite and len(pl) > 1:
            raise util.Abort(_("outstanding uncommitted merge"))
        if branchmerge:
            if pas == [p2]:
                raise util.Abort(_("merging with a working directory ancestor"
                                   " has no effect"))
            elif pas == [p1]:
                if not mergeancestor and p1.branch() == p2.branch():
                    raise util.Abort(_("nothing to merge"),
                                     hint=_("use 'hg update' "
                                            "or check 'hg heads'"))
            if not force and (wc.files() or wc.deleted()):
                raise util.Abort(_("uncommitted changes"),
                                 hint=_("use 'hg status' to list changes"))
            for s in sorted(wc.substate):
                wc.sub(s).bailifchanged()

        elif not overwrite:
            if p1 == p2: # no-op update
                # call the hooks and exit early
                repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
                repo.hook('update', parent1=xp2, parent2='', error=0)
                return 0, 0, 0, 0

            if pas not in ([p1], [p2]):  # nonlinear
                dirty = wc.dirty(missing=True)
                if dirty or onode is None:
                    # Branching is a bit strange to ensure we do the minimal
                    # amount of call to obsolete.background.
                    foreground = obsolete.foreground(repo, [p1.node()])
                    # note: the <node> variable contains a random identifier
                    if repo[node].node() in foreground:
                        pas = [p1]  # allow updating to successors
                    elif dirty:
                        msg = _("uncommitted changes")
                        if onode is None:
                            hint = _("commit and merge, or update --clean to"
                                     " discard changes")
                        else:
                            hint = _("commit or update --clean to discard"
                                     " changes")
                        raise util.Abort(msg, hint=hint)
                    else:  # node is none
                        msg = _("not a linear update")
                        hint = _("merge or update --check to force update")
                        raise util.Abort(msg, hint=hint)
                else:
                    # Allow jumping branches if clean and specific rev given
                    pas = [p1]

        followcopies = False
        if overwrite:
            pas = [wc]
        elif pas == [p2]: # backwards
            pas = [wc.p1()]
        elif not branchmerge and not wc.dirty(missing=True):
            pass
        elif pas[0] and repo.ui.configbool('merge', 'followcopies', True):
            followcopies = True

        ### calculate phase
        actionbyfile, diverge, renamedelete = calculateupdates(
            repo, wc, p2, pas, branchmerge, force, partial, mergeancestor,
            followcopies)
        # Convert to dictionary-of-lists format
        actions = dict((m, []) for m in 'a f g cd dc r dm dg m e k'.split())
        for f, (m, args, msg) in actionbyfile.iteritems():
            if m not in actions:
                actions[m] = []
            actions[m].append((f, args, msg))

        if not util.checkcase(repo.path):
            # check collision between files only in p2 for clean update
            if (not branchmerge and
                (force or not wc.dirty(missing=True, branch=False))):
                _checkcollision(repo, p2.manifest(), None)
            else:
                _checkcollision(repo, wc.manifest(), actions)

        # Prompt and create actions. TODO: Move this towards resolve phase.
        for f, args, msg in sorted(actions['cd']):
            if repo.ui.promptchoice(
                _("local changed %s which remote deleted\n"
                  "use (c)hanged version or (d)elete?"
                  "$$ &Changed $$ &Delete") % f, 0):
                actions['r'].append((f, None, "prompt delete"))
            else:
                actions['a'].append((f, None, "prompt keep"))
        del actions['cd'][:]

        for f, args, msg in sorted(actions['dc']):
            flags, = args
            if repo.ui.promptchoice(
                _("remote changed %s which local deleted\n"
                  "use (c)hanged version or leave (d)eleted?"
                  "$$ &Changed $$ &Deleted") % f, 0) == 0:
                actions['g'].append((f, (flags,), "prompt recreating"))
        del actions['dc'][:]

        ### apply phase
        if not branchmerge: # just jump to the new rev
            fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
        if not partial:
            repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
            # note that we're in the middle of an update
            repo.vfs.write('updatestate', p2.hex())

        stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)

        # divergent renames
        for f, fl in sorted(diverge.iteritems()):
            repo.ui.warn(_("note: possible conflict - %s was renamed "
                           "multiple times to:\n") % f)
            for nf in fl:
                repo.ui.warn(" %s\n" % nf)

        # rename and delete
        for f, fl in sorted(renamedelete.iteritems()):
            repo.ui.warn(_("note: possible conflict - %s was deleted "
                           "and renamed to:\n") % f)
            for nf in fl:
                repo.ui.warn(" %s\n" % nf)

        if not partial:
            repo.dirstate.beginparentchange()
            repo.setparents(fp1, fp2)
            recordupdates(repo, actions, branchmerge)
            # update completed, clear state
            util.unlink(repo.join('updatestate'))

            if not branchmerge:
                repo.dirstate.setbranch(p2.branch())
            repo.dirstate.endparentchange()
    finally:
        wlock.release()

    if not partial:
        def updatehook(parent1=xp1, parent2=xp2, error=stats[3]):
            repo.hook('update', parent1=parent1, parent2=parent2, error=error)
        repo._afterlock(updatehook)
    return stats
Example #38
0
def update(repo, node, branchmerge, force, partial, ancestor=None,
           mergeancestor=False):
    """
    Perform a merge between the working directory and the given node

    node = the node to update to, or None if unspecified
    branchmerge = whether to merge between branches
    force = whether to force branch merging or file overwriting
    partial = a function to filter file lists (dirstate not updated)
    mergeancestor = whether it is merging with an ancestor. If true,
      we should accept the incoming changes for any prompts that occur.
      If false, merging with an ancestor (fast-forward) is only allowed
      between different named branches. This flag is used by rebase extension
      as a temporary fix and should be avoided in general.

    The table below shows all the behaviors of the update command
    given the -c and -C or no options, whether the working directory
    is dirty, whether a revision is specified, and the relationship of
    the parent rev to the target rev (linear, on the same named
    branch, or on another named branch).

    This logic is tested by test-update-branches.t.

    -c  -C  dirty  rev  |  linear   same  cross
     n   n    n     n   |    ok     (1)     x
     n   n    n     y   |    ok     ok     ok
     n   n    y     *   |   merge   (2)    (2)
     n   y    *     *   |    ---  discard  ---
     y   n    y     *   |    ---    (3)    ---
     y   n    n     *   |    ---    ok     ---
     y   y    *     *   |    ---    (4)    ---

    x = can't happen
    * = don't-care
    1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
    2 = abort: crosses branches (use 'hg merge' to merge or
                 use 'hg update -C' to discard changes)
    3 = abort: uncommitted local changes
    4 = incompatible options (checked in commands.py)

    Return the same tuple as applyupdates().
    """

    onode = node
    wlock = repo.wlock()
    try:
        wc = repo[None]
        if node is None:
            # tip of current branch
            try:
                node = repo.branchtip(wc.branch())
            except error.RepoLookupError:
                if wc.branch() == "default": # no default branch!
                    node = repo.lookup("tip") # update to tip
                else:
                    raise util.Abort(_("branch %s not found") % wc.branch())
        overwrite = force and not branchmerge
        pl = wc.parents()
        p1, p2 = pl[0], repo[node]
        if ancestor:
            pa = repo[ancestor]
        else:
            pa = p1.ancestor(p2)

        fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)

        ### check phase
        if not overwrite and len(pl) > 1:
            raise util.Abort(_("outstanding uncommitted merges"))
        if branchmerge:
            if pa == p2:
                raise util.Abort(_("merging with a working directory ancestor"
                                   " has no effect"))
            elif pa == p1:
                if not mergeancestor and p1.branch() == p2.branch():
                    raise util.Abort(_("nothing to merge"),
                                     hint=_("use 'hg update' "
                                            "or check 'hg heads'"))
            if not force and (wc.files() or wc.deleted()):
                raise util.Abort(_("outstanding uncommitted changes"),
                                 hint=_("use 'hg status' to list changes"))
            for s in sorted(wc.substate):
                if wc.sub(s).dirty():
                    raise util.Abort(_("outstanding uncommitted changes in "
                                       "subrepository '%s'") % s)

        elif not overwrite:
            if pa not in (p1, p2):  # nolinear
                dirty = wc.dirty(missing=True)
                if dirty or onode is None:
                    # Branching is a bit strange to ensure we do the minimal
                    # amount of call to obsolete.background.
                    foreground = obsolete.foreground(repo, [p1.node()])
                    # note: the <node> variable contains a random identifier
                    if repo[node].node() in foreground:
                        pa = p1  # allow updating to successors
                    elif dirty:
                        msg = _("crosses branches (merge branches or use"
                                " --clean to discard changes)")
                        raise util.Abort(msg)
                    else:  # node is none
                        msg = _("crosses branches (merge branches or update"
                                " --check to force update)")
                        raise util.Abort(msg)
                else:
                    # Allow jumping branches if clean and specific rev given
                    pa = p1

        ### calculate phase
        actions = calculateupdates(repo, wc, p2, pa,
                                   branchmerge, force, partial, mergeancestor)

        ### apply phase
        if not branchmerge: # just jump to the new rev
            fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
        if not partial:
            repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
            # note that we're in the middle of an update
            repo.vfs.write('updatestate', p2.hex())

        stats = applyupdates(repo, actions, wc, p2, pa, overwrite)

        if not partial:
            repo.setparents(fp1, fp2)
            recordupdates(repo, actions, branchmerge)
            # update completed, clear state
            util.unlink(repo.join('updatestate'))

            if not branchmerge:
                repo.dirstate.setbranch(p2.branch())
    finally:
        wlock.release()

    if not partial:
        repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
    return stats
Example #39
0
def update(repo, node, branchmerge, force, partial, ancestor=None,
           mergeancestor=False):
    """
    Perform a merge between the working directory and the given node

    node = the node to update to, or None if unspecified
    branchmerge = whether to merge between branches
    force = whether to force branch merging or file overwriting
    partial = a function to filter file lists (dirstate not updated)
    mergeancestor = whether it is merging with an ancestor. If true,
      we should accept the incoming changes for any prompts that occur.
      If false, merging with an ancestor (fast-forward) is only allowed
      between different named branches. This flag is used by rebase extension
      as a temporary fix and should be avoided in general.

    The table below shows all the behaviors of the update command
    given the -c and -C or no options, whether the working directory
    is dirty, whether a revision is specified, and the relationship of
    the parent rev to the target rev (linear, on the same named
    branch, or on another named branch).

    This logic is tested by test-update-branches.t.

    -c  -C  dirty  rev  |  linear   same  cross
     n   n    n     n   |    ok     (1)     x
     n   n    n     y   |    ok     ok     ok
     n   n    y     n   |   merge   (2)    (2)
     n   n    y     y   |   merge   (3)    (3)
     n   y    *     *   |    ---  discard  ---
     y   n    y     *   |    ---    (4)    ---
     y   n    n     *   |    ---    ok     ---
     y   y    *     *   |    ---    (5)    ---

    x = can't happen
    * = don't-care
    1 = abort: not a linear update (merge or update --check to force update)
    2 = abort: uncommitted changes (commit and merge, or update --clean to
                 discard changes)
    3 = abort: uncommitted changes (commit or update --clean to discard changes)
    4 = abort: uncommitted changes (checked in commands.py)
    5 = incompatible options (checked in commands.py)

    Return the same tuple as applyupdates().
    """

    onode = node
    wlock = repo.wlock()
    try:
        wc = repo[None]
        if node is None:
            # tip of current branch
            try:
                node = repo.branchtip(wc.branch())
            except error.RepoLookupError:
                if wc.branch() == "default": # no default branch!
                    node = repo.lookup("tip") # update to tip
                else:
                    raise util.Abort(_("branch %s not found") % wc.branch())
        overwrite = force and not branchmerge
        pl = wc.parents()
        p1, p2 = pl[0], repo[node]
        if ancestor:
            pa = repo[ancestor]
        else:
            pa = p1.ancestor(p2)

        fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)

        ### check phase
        if not overwrite and len(pl) > 1:
            raise util.Abort(_("outstanding uncommitted merges"))
        if branchmerge:
            if pa == p2:
                raise util.Abort(_("merging with a working directory ancestor"
                                   " has no effect"))
            elif pa == p1:
                if not mergeancestor and p1.branch() == p2.branch():
                    raise util.Abort(_("nothing to merge"),
                                     hint=_("use 'hg update' "
                                            "or check 'hg heads'"))
            if not force and (wc.files() or wc.deleted()):
                raise util.Abort(_("uncommitted changes"),
                                 hint=_("use 'hg status' to list changes"))
            for s in sorted(wc.substate):
                if wc.sub(s).dirty():
                    raise util.Abort(_("uncommitted changes in "
                                       "subrepository '%s'") % s)

        elif not overwrite:
            if pa not in (p1, p2):  # nolinear
                dirty = wc.dirty(missing=True)
                if dirty or onode is None:
                    # Branching is a bit strange to ensure we do the minimal
                    # amount of call to obsolete.background.
                    foreground = obsolete.foreground(repo, [p1.node()])
                    # note: the <node> variable contains a random identifier
                    if repo[node].node() in foreground:
                        pa = p1  # allow updating to successors
                    elif dirty:
                        msg = _("uncommitted changes")
                        if onode is None:
                            hint = _("commit and merge, or update --clean to"
                                     " discard changes")
                        else:
                            hint = _("commit or update --clean to discard"
                                     " changes")
                        raise util.Abort(msg, hint=hint)
                    else:  # node is none
                        msg = _("not a linear update")
                        hint = _("merge or update --check to force update")
                        raise util.Abort(msg, hint=hint)
                else:
                    # Allow jumping branches if clean and specific rev given
                    pa = p1

        ### calculate phase
        actions = calculateupdates(repo, wc, p2, pa,
                                   branchmerge, force, partial, mergeancestor)

        ### apply phase
        if not branchmerge: # just jump to the new rev
            fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
        if not partial:
            repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
            # note that we're in the middle of an update
            repo.vfs.write('updatestate', p2.hex())

        stats = applyupdates(repo, actions, wc, p2, pa, overwrite)

        if not partial:
            repo.setparents(fp1, fp2)
            recordupdates(repo, actions, branchmerge)
            # update completed, clear state
            util.unlink(repo.join('updatestate'))

            if not branchmerge:
                repo.dirstate.setbranch(p2.branch())
    finally:
        wlock.release()

    if not partial:
        repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
    return stats
def applyupdates(repo, action, wctx, mctx, actx, overwrite):
    """apply the merge action list to the working directory

    wctx is the working copy context
    mctx is the context to be merged into the working copy
    actx is the context of the common ancestor
    """

    updated, merged, removed, unresolved = 0, 0, 0, 0
    ms = mergestate(repo)
    ms.reset(wctx.parents()[0].node())
    moves = []
    action.sort(key=actionkey)
    substate = wctx.substate  # prime

    # prescan for merges
    u = repo.ui
    for a in action:
        f, m = a[:2]
        if m == 'm':  # merge
            f2, fd, flags, move = a[2:]
            if f == '.hgsubstate':  # merged internally
                continue
            repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
            fcl = wctx[f]
            fco = mctx[f2]
            if mctx == actx:  # backwards, use working dir parent as ancestor
                if fcl.parents():
                    fca = fcl.parents()[0]
                else:
                    fca = repo.filectx(f, fileid=nullrev)
            else:
                fca = fcl.ancestor(fco, actx)
            if not fca:
                fca = repo.filectx(f, fileid=nullrev)
            ms.add(fcl, fco, fca, fd, flags)
            if f != fd and move:
                moves.append(f)

    # remove renamed files after safely stored
    for f in moves:
        if os.path.lexists(repo.wjoin(f)):
            repo.ui.debug("removing %s\n" % f)
            os.unlink(repo.wjoin(f))

    audit_path = util.path_auditor(repo.root)

    numupdates = len(action)
    for i, a in enumerate(action):
        f, m = a[:2]
        u.progress(_('updating'),
                   i + 1,
                   item=f,
                   total=numupdates,
                   unit=_('files'))
        if f and f[0] == "/":
            continue
        if m == "r":  # remove
            repo.ui.note(_("removing %s\n") % f)
            audit_path(f)
            if f == '.hgsubstate':  # subrepo states need updating
                subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
            try:
                util.unlink(repo.wjoin(f))
            except OSError, inst:
                if inst.errno != errno.ENOENT:
                    repo.ui.warn(
                        _("update failed to remove %s: %s!\n") %
                        (f, inst.strerror))
            removed += 1
        elif m == "m":  # merge
            if f == '.hgsubstate':  # subrepo states need updating
                subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
                                 overwrite)
                continue
            f2, fd, flags, move = a[2:]
            r = ms.resolve(fd, wctx, mctx)
            if r is not None and r > 0:
                unresolved += 1
            else:
                if r is None:
                    updated += 1
                else:
                    merged += 1
            util.set_flags(repo.wjoin(fd), 'l' in flags, 'x' in flags)
            if f != fd and move and os.path.lexists(repo.wjoin(f)):
                repo.ui.debug("removing %s\n" % f)
                os.unlink(repo.wjoin(f))
                fp = opener(f, 'a')
                fp.truncate(o)
                fp.close()
            except IOError:
                report(_("failed to truncate %s\n") % f)
                raise
        else:
            try:
                fp = opener(f)
                fn = fp.name
                fp.close()
                util.unlink(fn)
            except (IOError, OSError), inst:
                if inst.errno != errno.ENOENT:
                    raise
    util.unlink(journal)

class transaction(object):
    def __init__(self, report, opener, journal, after=None, createmode=None):
        self.count = 1
        self.usages = 1
        self.report = report
        self.opener = opener
        self.after = after
        self.entries = []
        self.map = {}
        self.journal = journal
        self._queue = []

        self.file = util.posixfile(self.journal, "w")
        if createmode is not None:
Example #42
0
            if f != fd and move and util.lexists(repo.wjoin(f)):
                repo.ui.debug(_("removing %s\n") % f)
                os.unlink(repo.wjoin(f))
        elif m == "g": # get
            flags = a[2]
            repo.ui.note(_("getting %s\n") % f)
            t = mctx.filectx(f).data()
            repo.wwrite(f, t, flags)
            updated += 1
        elif m == "d": # directory rename
            f2, fd, flags = a[2:]
            if f:
                repo.ui.note(_("moving %s to %s\n") % (f, fd))
                t = wctx.filectx(f).data()
                repo.wwrite(fd, t, flags)
                util.unlink(repo.wjoin(f))
            if f2:
                repo.ui.note(_("getting %s to %s\n") % (f2, fd))
                t = mctx.filectx(f2).data()
                repo.wwrite(fd, t, flags)
            updated += 1
        elif m == "dr": # divergent renames
            fl = a[2]
            repo.ui.warn("warning: detected divergent renames of %s to:\n" % f)
            for nf in fl:
                repo.ui.warn(" %s\n" % nf)
        elif m == "e": # exec
            flags = a[2]
            util.set_flags(repo.wjoin(f), 'l' in flags, 'x' in flags)

    return updated, merged, removed, unresolved
Example #43
0
def update(repo, node, branchmerge, force, partial, ancestor=None,
           mergeancestor=False):
    """
    Perform a merge between the working directory and the given node

    node = the node to update to, or None if unspecified
    branchmerge = whether to merge between branches
    force = whether to force branch merging or file overwriting
    partial = a function to filter file lists (dirstate not updated)
    mergeancestor = whether it is merging with an ancestor. If true,
      we should accept the incoming changes for any prompts that occur.
      If false, merging with an ancestor (fast-forward) is only allowed
      between different named branches. This flag is used by rebase extension
      as a temporary fix and should be avoided in general.

    The table below shows all the behaviors of the update command
    given the -c and -C or no options, whether the working directory
    is dirty, whether a revision is specified, and the relationship of
    the parent rev to the target rev (linear, on the same named
    branch, or on another named branch).

    This logic is tested by test-update-branches.t.

    -c  -C  dirty  rev  |  linear   same  cross
     n   n    n     n   |    ok     (1)     x
     n   n    n     y   |    ok     ok     ok
     n   n    y     n   |   merge   (2)    (2)
     n   n    y     y   |   merge   (3)    (3)
     n   y    *     *   |    ---  discard  ---
     y   n    y     *   |    ---    (4)    ---
     y   n    n     *   |    ---    ok     ---
     y   y    *     *   |    ---    (5)    ---

    x = can't happen
    * = don't-care
    1 = abort: not a linear update (merge or update --check to force update)
    2 = abort: uncommitted changes (commit and merge, or update --clean to
                 discard changes)
    3 = abort: uncommitted changes (commit or update --clean to discard changes)
    4 = abort: uncommitted changes (checked in commands.py)
    5 = incompatible options (checked in commands.py)

    Return the same tuple as applyupdates().
    """

    onode = node
    wlock = repo.wlock()
    try:
        wc = repo[None]
        pl = wc.parents()
        p1 = pl[0]
        pas = [None]
        if ancestor:
            pas = [repo[ancestor]]

        if node is None:
            # Here is where we should consider bookmarks, divergent bookmarks,
            # foreground changesets (successors), and tip of current branch;
            # but currently we are only checking the branch tips.
            try:
                node = repo.branchtip(wc.branch())
            except error.RepoLookupError:
                if wc.branch() == "default": # no default branch!
                    node = repo.lookup("tip") # update to tip
                else:
                    raise util.Abort(_("branch %s not found") % wc.branch())

            if p1.obsolete() and not p1.children():
                # allow updating to successors
                successors = obsolete.successorssets(repo, p1.node())

                # behavior of certain cases is as follows,
                #
                # divergent changesets: update to highest rev, similar to what
                #     is currently done when there are more than one head
                #     (i.e. 'tip')
                #
                # replaced changesets: same as divergent except we know there
                # is no conflict
                #
                # pruned changeset: no update is done; though, we could
                #     consider updating to the first non-obsolete parent,
                #     similar to what is current done for 'hg prune'

                if successors:
                    # flatten the list here handles both divergent (len > 1)
                    # and the usual case (len = 1)
                    successors = [n for sub in successors for n in sub]

                    # get the max revision for the given successors set,
                    # i.e. the 'tip' of a set
                    node = repo.revs("max(%ln)", successors)[0]
                    pas = [p1]

        overwrite = force and not branchmerge

        p2 = repo[node]
        if pas[0] is None:
            if repo.ui.config("merge", "preferancestor") == '*':
                cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
                pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
            else:
                pas = [p1.ancestor(p2, warn=True)]

        fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)

        ### check phase
        if not overwrite and len(pl) > 1:
            raise util.Abort(_("outstanding uncommitted merges"))
        if branchmerge:
            if pas == [p2]:
                raise util.Abort(_("merging with a working directory ancestor"
                                   " has no effect"))
            elif pas == [p1]:
                if not mergeancestor and p1.branch() == p2.branch():
                    raise util.Abort(_("nothing to merge"),
                                     hint=_("use 'hg update' "
                                            "or check 'hg heads'"))
            if not force and (wc.files() or wc.deleted()):
                raise util.Abort(_("uncommitted changes"),
                                 hint=_("use 'hg status' to list changes"))
            for s in sorted(wc.substate):
                if wc.sub(s).dirty():
                    raise util.Abort(_("uncommitted changes in "
                                       "subrepository '%s'") % s)

        elif not overwrite:
            if p1 == p2: # no-op update
                # call the hooks and exit early
                repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
                repo.hook('update', parent1=xp2, parent2='', error=0)
                return 0, 0, 0, 0

            if pas not in ([p1], [p2]):  # nonlinear
                dirty = wc.dirty(missing=True)
                if dirty or onode is None:
                    # Branching is a bit strange to ensure we do the minimal
                    # amount of call to obsolete.background.
                    foreground = obsolete.foreground(repo, [p1.node()])
                    # note: the <node> variable contains a random identifier
                    if repo[node].node() in foreground:
                        pas = [p1]  # allow updating to successors
                    elif dirty:
                        msg = _("uncommitted changes")
                        if onode is None:
                            hint = _("commit and merge, or update --clean to"
                                     " discard changes")
                        else:
                            hint = _("commit or update --clean to discard"
                                     " changes")
                        raise util.Abort(msg, hint=hint)
                    else:  # node is none
                        msg = _("not a linear update")
                        hint = _("merge or update --check to force update")
                        raise util.Abort(msg, hint=hint)
                else:
                    # Allow jumping branches if clean and specific rev given
                    pas = [p1]

        followcopies = False
        if overwrite:
            pas = [wc]
        elif pas == [p2]: # backwards
            pas = [wc.p1()]
        elif not branchmerge and not wc.dirty(missing=True):
            pass
        elif pas[0] and repo.ui.configbool("merge", "followcopies", True):
            followcopies = True

        ### calculate phase
        actions = calculateupdates(repo, wc, p2, pas, branchmerge, force,
                                   partial, mergeancestor, followcopies)

        ### apply phase
        if not branchmerge: # just jump to the new rev
            fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
        if not partial:
            repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
            # note that we're in the middle of an update
            repo.vfs.write('updatestate', p2.hex())

        stats = applyupdates(repo, actions, wc, p2, overwrite)

        if not partial:
            repo.setparents(fp1, fp2)
            recordupdates(repo, actions, branchmerge)
            # update completed, clear state
            util.unlink(repo.join('updatestate'))

            if not branchmerge:
                repo.dirstate.setbranch(p2.branch())
    finally:
        wlock.release()

    if not partial:
        repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
    return stats
Example #44
0
                fp = opener(f, 'a')
                fp.truncate(o)
                fp.close()
            except IOError:
                report(_("failed to truncate %s\n") % f)
                raise
        else:
            try:
                fp = opener(f)
                fn = fp.name
                fp.close()
                util.unlink(fn)
            except (IOError, OSError), inst:
                if inst.errno != errno.ENOENT:
                    raise
    util.unlink(journal)


class transaction(object):
    def __init__(self, report, opener, journal, after=None, createmode=None):
        self.count = 1
        self.usages = 1
        self.report = report
        self.opener = opener
        self.after = after
        self.entries = []
        self.map = {}
        self.journal = journal
        self._queue = []

        self.file = util.posixfile(self.journal, "w")
Example #45
0
def applyupdates(repo, action, wctx, mctx, actx, overwrite):
    """apply the merge action list to the working directory

    wctx is the working copy context
    mctx is the context to be merged into the working copy
    actx is the context of the common ancestor
    """

    updated, merged, removed, unresolved = 0, 0, 0, 0
    ms = mergestate(repo)
    ms.reset(wctx.parents()[0].node())
    moves = []
    action.sort(key=actionkey)
    substate = wctx.substate # prime

    # prescan for merges
    u = repo.ui
    for a in action:
        f, m = a[:2]
        if m == 'm': # merge
            f2, fd, flags, move = a[2:]
            if f == '.hgsubstate': # merged internally
                continue
            repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
            fcl = wctx[f]
            fco = mctx[f2]
            if mctx == actx: # backwards, use working dir parent as ancestor
                if fcl.parents():
                    fca = fcl.parents()[0]
                else:
                    fca = repo.filectx(f, fileid=nullrev)
            else:
                fca = fcl.ancestor(fco, actx)
            if not fca:
                fca = repo.filectx(f, fileid=nullrev)
            ms.add(fcl, fco, fca, fd, flags)
            if f != fd and move:
                moves.append(f)

    # remove renamed files after safely stored
    for f in moves:
        if os.path.lexists(repo.wjoin(f)):
            repo.ui.debug("removing %s\n" % f)
            os.unlink(repo.wjoin(f))

    audit_path = util.path_auditor(repo.root)

    numupdates = len(action)
    for i, a in enumerate(action):
        f, m = a[:2]
        u.progress(_('updating'), i + 1, item=f, total=numupdates,
                   unit=_('files'))
        if f and f[0] == "/":
            continue
        if m == "r": # remove
            repo.ui.note(_("removing %s\n") % f)
            audit_path(f)
            if f == '.hgsubstate': # subrepo states need updating
                subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
            try:
                util.unlink(repo.wjoin(f))
            except OSError, inst:
                if inst.errno != errno.ENOENT:
                    repo.ui.warn(_("update failed to remove %s: %s!\n") %
                                 (f, inst.strerror))
            removed += 1
        elif m == "m": # merge
            if f == '.hgsubstate': # subrepo states need updating
                subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
                continue
            f2, fd, flags, move = a[2:]
            r = ms.resolve(fd, wctx, mctx)
            if r is not None and r > 0:
                unresolved += 1
            else:
                if r is None:
                    updated += 1
                else:
                    merged += 1
            util.set_flags(repo.wjoin(fd), 'l' in flags, 'x' in flags)
            if f != fd and move and os.path.lexists(repo.wjoin(f)):
                repo.ui.debug("removing %s\n" % f)
                os.unlink(repo.wjoin(f))
Example #46
0
 def unlink(self, path=None):
     return util.unlink(self.join(path))
Example #47
0
            host, pid = locker.split(":", 1)
        except ValueError:
            return locker
        if host != lock._host:
            return locker
        try:
            pid = int(pid)
        except ValueError:
            return locker
        if util.testpid(pid):
            return locker
        # if locker dead, break lock.  must do this with another lock
        # held, or can race and break valid lock.
        try:
            l = lock(self.f + '.break', timeout=0)
            util.unlink(self.f)
            l.release()
        except error.LockError:
            return locker

    def release(self):
        """release the lock and execute callback function if any

        If the lock has been acquired multiple times, the actual release is
        delayed to the last release call."""
        if self.held > 1:
            self.held -= 1
        elif self.held == 1:
            self.held = 0
            if os.getpid() != self.pid:
                # we forked, and are not the parent