Exemplo n.º 1
0
    def refresh(self, patch_name=None, edit=False):
        """ Refresh patch with patch_name or applied top patch if patch_name is
        None
        """
        if patch_name:
            patch = Patch(patch_name)
        else:
            patch = self.db.top_patch()

            if not patch:
                raise QuiltError("No patch applied. Nothing to refresh.")

        pc_dir = self.quilt_pc + patch.get_name()
        patch_file = self.quilt_patches + File(patch.get_name())
        files = pc_dir.content()[1]

        with TmpFile(prefix="pquilt-") as tmpfile:
            f = tmpfile.open()

            if patch_file.exists():
                header = patch.get_header(self.quilt_patches)
                tmpfile.write(header)

            for file_name in files:
                if file_name == ".timestamp":
                    continue
                orig_file = pc_dir + File(file_name)
                new_file = File(file_name)
                left_label, right_label, index = self._get_labels(
                    file_name, orig_file, new_file)
                self._write_index(tmpfile, index)

                diff = Diff(orig_file, new_file)
                diff.run(self.cwd,
                         fd=f,
                         left_label=left_label,
                         right_label=right_label)

            if tmpfile.is_empty():
                raise QuiltError("Nothing to refresh.")

            if edit:
                self.edit_patch(tmpfile)
                tpatch = Patch(tmpfile.get_name())
                tpatch.run(pc_dir.get_name(), dry_run=True, quiet=True)

            if patch_file.exists():
                diff = Diff(patch_file, tmpfile)
                if diff.equal(self.cwd):
                    raise QuiltError("Nothing to refresh.")

            tmpfile.copy(patch_file)

        timestamp = pc_dir + File(".timestamp")
        timestamp.touch()

        refresh = self.quilt_pc + File(patch.get_name() + "~refresh")
        refresh.delete_if_exists()

        self.refreshed(patch)
Exemplo n.º 2
0
    def add_file(self, filename, patch_name=None, ignore=False):
        """ Add file to the patch with patch_name.
        If patch_name is None or empty the topmost patch will be used.
        Adding an already added patch will raise an QuiltError if ignore is
        False.
        """
        file = File(filename)

        if patch_name:
            patch = Patch(patch_name)
        else:
            patch = self.db.top_patch()
            if not patch:
                raise NoAppliedPatch(self.db)

        exists = self._file_in_patch(filename, patch, ignore)
        if exists:
            return

        self._file_in_next_patches(filename, patch)

        if file.is_link():
            raise QuiltError("Cannot add symbolic link %s" % filename)

        self._backup_file(file, patch)

        if file.exists():
            # be sure user can write original file
            os.chmod(filename, file.get_mode() | stat.S_IWUSR | stat.S_IRUSR)

        self.file_added(file, patch)
Exemplo n.º 3
0
    def run(self, suppress_output=False, inputdata=None, **kw):
        """Run command as a subprocess and wait until it is finished.

        The command should be given as a list of strings to avoid problems
        with shell quoting.  If the command exits with a return code other
        than 0, a SubprocessError is raised.
        """
        if inputdata is not None:
            kw["stdin"] = subprocess.PIPE
        if suppress_output:
            kw["stdout"] = open(os.devnull, "w")
            kw["stderr"] = kw["stdout"]
        try:
            try:
                process = subprocess.Popen(self.cmd, **kw)
            finally:
                if suppress_output:
                    kw["stdout"].close()
        except OSError as e:
            msg = "Failed starting command {!r}: {}".format(self.cmd, e)
            raise QuiltError(msg)

        if inputdata is not None:
            process.stdin.write(inputdata)
            process.stdin.close()
        ret = process.wait()
        if ret != 0:
            raise SubprocessError(self.cmd, ret)
Exemplo n.º 4
0
 def _file_in_patch(self, filename, patch):
     """ Checks if a backup file of the filename in the current patch
     exists and raises a QuiltError if not.
     """
     pc_dir = self.quilt_pc + patch.get_name()
     file = pc_dir + File(filename)
     if not file.exists():
         raise QuiltError("File %s is not in patch %s" %
                          (filename, patch.get_name()))
Exemplo n.º 5
0
 def _check(self, force=False):
     if not self.db.exists() or not self.db.patches():
         raise NoAppliedPatch(self.db)
     if not force:
         patch = self.db.top_patch()
         pc_dir = self.quilt_pc + patch.get_name()
         refresh = File(pc_dir.get_name() + "~refresh")
         if refresh.exists():
             raise QuiltError("Patch %s needs to be refreshed first." %
                              patch.get_name())
Exemplo n.º 6
0
 def _file_in_patch(self, filename, patch, ignore):
     """ Checks if a backup file of the filename in the current patch
     exists """
     file = self.quilt_pc + File(os.path.join(patch.get_name(), filename))
     if file.exists():
         if ignore:
             return True
         else:
             raise QuiltError("File %s is already in patch %s" % (filename,
                              patch.get_name()))
     return False
Exemplo n.º 7
0
 def _check(self):
     if not self.series.exists() or not self.series.patches():
         raise NoPatchesInSeries(self.series)
     
     top = self.db.top_patch()
     if top is not None:
         refresh = top.get_name() + "~refresh"
         refresh = os.path.join(self.quilt_pc.get_name(), refresh)
         if os.path.exists(refresh):
             raise QuiltError("Patch %s needs to be refreshed" % \
                                   top.get_name())
Exemplo n.º 8
0
    def _apply_patch(self, patch, force=False, quiet=False):
        patch_name = patch.get_name()
        pc_dir = self.quilt_pc + patch_name
        patch_file = self.quilt_patches + File(patch_name)
        refresh = File(pc_dir.get_name() + "~refresh")

        forced = False
        self.applying_patch(patch)

        if patch_file.exists():
            try:
                patch.run(self.cwd, patch_dir=self.quilt_patches, backup=True,
                          prefix=pc_dir.get_name(), quiet=quiet)
            except SubprocessError as e:
                if not force:
                    patch = RollbackPatch(self.cwd, pc_dir)
                    patch.rollback()
                    patch.delete_backup()
                    raise QuiltError("Patch %s does not apply" % patch_name)
                else:
                    refresh.touch()
                    forced = True

        self.db.add_patch(patch)

        if pc_dir.exists():
            timestamp = pc_dir + File(".timestamp")
            timestamp.touch()
        else:
            pc_dir.create()

        if not patch_file.exists():
            self.applied_empty_patch(patch, False)
        elif pc_dir.is_empty():
            self.applied_empty_patch(patch, True)
        elif forced:
            raise QuiltError("Applied patch %s (forced; needs refresh)" %
                             patch.get_name())
        else:
            self.applied_patch(patch)
Exemplo n.º 9
0
    def delete_next(self, remove=False, backup=False):
        """ Delete next unapplied patch
        If remove is True the patch file will also be removed. If remove and
        backup are True a copy of the deleted patch file will be made.
        """
        patch = self.db.top_patch()
        if patch:
            after = self.series.patch_after(patch)
        else:
            after = self.series.first_patch()
        if not after:
            raise QuiltError("No next patch")

        self._delete_patch(after, remove=remove, backup=backup)
Exemplo n.º 10
0
    def _file_in_next_patches(self, filename, patch):
        """ Checks if a backup file of the filename in the applied patches after
        patch exists """

        if not self.db.is_patch(patch):
            # no patches applied
            return

        patches = self.db.patches_after(patch)
        for patch in patches:
            file = self.quilt_pc + File(os.path.join(patch.get_name(),
                                                     filename))
            if file.exists():
                raise QuiltError("File %s is already modified by patch %s" %
                                 (filename, patch.get_name()))
Exemplo n.º 11
0
    def revert_file(self, filename, patch_name=None):
        """ Revert not added changes of filename.
        If patch_name is None or empty the topmost patch will be used.
        """
        file = File(filename)

        if patch_name:
            patch = Patch(patch_name)
        else:
            patch = self.db.top_patch()

            if not patch:
                raise QuiltError("No patch available. Nothing to revert.")

        self._file_in_patch(filename, patch)
        self._file_in_next_patches(filename, patch)
        pc_dir = self.quilt_pc + patch.get_name()
        pc_file = pc_dir + file

        if not file.exists() and pc_file.is_empty():
            # new and empty file will be reverted
            pc_file.delete()
            self.file_reverted(file, patch)
            return

        with TmpDirectory(prefix="pquilt-") as tmpdir:
            # apply current patch in temporary directory to revert changes of
            # file that aren't committed in the patch
            tmp_file = self._apply_patch_temporary(tmpdir, pc_file, patch)
            if tmp_file and tmp_file.exists() and not tmp_file.is_empty():

                diff = Diff(file, tmp_file)
                if diff.equal(self.cwd):
                    self.file_unchanged(file, patch)
                    return

                dir = file.get_directory()
                if not dir:
                    dir = Directory(os.getcwd())
                else:
                    dir.create()
                tmp_file.copy(dir)
                self.file_reverted(file, patch)
            else:
                self.file_unchanged(file, patch)