Esempio n. 1
0
    def test_apply_next(self):
        patch1 = Patch("p1.patch")
        patch2 = Patch("p2.patch")

        test_dir = self.data_dir + "test1"

        with TmpDirectory(dir=self.data_dir.get_name()) as tmp_dir:
            tmp_test_dir = tmp_dir + "test2"

            test_dir.copy(tmp_test_dir)

            pc_dir = tmp_test_dir + "pc"

            f1 = tmp_test_dir + File("f1")
            self.assertTrue(f1.exists())
            f2 = tmp_test_dir + File("f2")
            self.assertTrue(f2.exists())

            pop = Pop(tmp_test_dir.get_name(), pc_dir.get_name())
            self.assertEqual(patch2, pop.db.top_patch())

            pop.unapply_top_patch()
            self.assertEqual(patch1, pop.db.top_patch())

            self.assertTrue(f1.exists())
            self.assertFalse(f2.exists())

            pop.unapply_top_patch()
            self.assertEqual(None, pop.db.top_patch())

            self.assertFalse(f1.exists())
            self.assertFalse(f2.exists())
Esempio n. 2
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)
Esempio n. 3
0
    def test_apply_next(self):
        patch1 = Patch("p1.patch")
        patch2 = Patch("p2.patch")

        test_dir = self.data_dir + "test2"

        with TmpDirectory(dir=self.data_dir.get_name()) as tmp_dir:
            tmp_test_dir = tmp_dir + "test2"
            test_dir.copy(tmp_test_dir)

            pc_dir = tmp_test_dir + "pc"
            patches_dir = tmp_test_dir + "patches"

            f1 = tmp_test_dir + File("f1")
            self.assertFalse(f1.exists())
            f2 = tmp_test_dir + File("f2")
            self.assertFalse(f2.exists())

            push = Push(tmp_test_dir.get_name(), pc_dir.get_name(),
                        patches_dir.get_name())
            self.assertEqual(None, push.db.top_patch())

            push.apply_next_patch(quiet=True)
            self.assertEqual(patch1, push.db.top_patch())

            self.assertTrue(f1.exists())
            self.assertFalse(f2.exists())

            push.apply_next_patch(quiet=True)
            self.assertEqual(patch2, push.db.top_patch())

            self.assertTrue(f1.exists())
            self.assertTrue(f2.exists())
Esempio n. 4
0
    def _delete_patch(self, patch, remove=False, backup=False):
        if self.series.is_empty():
            raise NoPatchesInSeries(self.series)
        if not self.series.is_patch(patch):
            raise UnknownPatch(self.series, patch)

        applied = self.db.top_patch() == patch
        self.deleting_patch(patch, applied)

        if applied:
            self.pop._unapply_patch(patch)
            self.db = self.pop.db
            self.db.save()

        self.series.remove_patch(patch)
        self.series.save()

        patch_file = self.quilt_patches + File(patch.get_name())

        if remove:
            if backup:
                patch_file.copy(File(patch_file.get_name() + "~"))

            patch_file.delete_if_exists()

        self.deleted_patch(patch)
Esempio n. 5
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)
Esempio n. 6
0
class Diff(object):
    """ Wrapper around the diff util
    """

    @FileParam(["left", "right"])
    def __init__(self, left, right):
        """ left points to the first file and right to the second file
        """
        self.left = left
        if not self.left.exists():
            self.left = File("/dev/null")

        self.right = right
        if not self.right.exists():
            self.right = File("/dev/null")

    def run(self, cwd, left_label=None, right_label=None, unified=True,
            fd=None):
        cmd = ["diff"]

        if unified:
            cmd.append("-u")

        if left_label:
            cmd.append("--label")
            cmd.append(left_label)

        if right_label:
            if not left_label:
                cmd.append("--label")
                cmd.append(self.right.get_name())
            cmd.append("--label")
            cmd.append(right_label)

        cmd.append(self.left.get_name())
        cmd.append(self.right.get_name())

        try:
            Process(cmd).run(cwd=cwd, stdout=fd)
        except SubprocessError as e:
            if e.get_returncode() > 1:
                raise e

    def equal(self, cwd):
        """ Returns True if left and right are equal
        """
        cmd = ["diff"]
        cmd.append("-q")
        cmd.append(self.left.get_name())
        cmd.append(self.right.get_name())

        try:
            Process(cmd).run(cwd=cwd, suppress_output=True)
        except SubprocessError as e:
            if e.get_returncode() == 1:
                return False
            else:
                raise e
        return True
Esempio n. 7
0
 def backup_dir(self, src_dir, dest_dir, copy_empty=False):
     for file_name in src.files():
         file = File(file_name)
         file_dir = file.get_directory()
         if file_dir:
             dest = dest_dir + file_dir
         else:
             dest = dest_dir
         self.backup_file(file, dest, copy_empty)
Esempio n. 8
0
 def backup_dir(self, src_dir, dest_dir, copy_empty=False):
     for file_name in src_dir.files():
         file = File(file_name)
         file_dir = file.get_directory()
         if file_dir:
             dest = dest_dir + file_dir
         else:
             dest = dest_dir
         self.backup_file(file, dest, copy_empty)
Esempio n. 9
0
    def __init__(self, left, right):
        """ left points to the first file and right to the second file
        """
        self.left = left
        if not self.left.exists():
            self.left = File("/dev/null")

        self.right = right
        if not self.right.exists():
            self.right = File("/dev/null")
Esempio n. 10
0
    def __init__(self, left, right):
        """ left points to the first file and right to the second file
        """
        self.left = left
        if not self.left.exists():
            self.left = File("/dev/null")

        self.right = right
        if not self.right.exists():
            self.right = File("/dev/null")
Esempio n. 11
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())
Esempio n. 12
0
    def import_patches(self, patches):
        """ Import several patches into the patch queue """

        dest_dir = self.quilt_patches
        patch_names = []

        for patch in patches:
            patch_name = os.path.basename(patch)
            patch_file = File(patch)
            dest_file = dest_dir + File(patch_name)
            patch_file.copy(dest_file)
            patch_names.append(patch_name)

        self._import_patches(patch_names)
Esempio n. 13
0
    def create(self, patchname):
        """ Adds a new patch with patchname to the queue

        The new patch will be added as the topmost applied patch.
        """
        patch = Patch(patchname)
        if self.series.is_patch(patch):
            raise PatchAlreadyExists(self.series, patchname)

        patch_dir = self.quilt_patches
        patch_dir.create()
        patchfile = patch_dir + File(patchname)
        patchfile.touch()

        pc_dir = self.quilt_pc + patchname
        if pc_dir.exists():
            # be sure that the directory is clear
            pc_dir.delete()

        # create empty .pc/<patchname> directory as quilt does too
        pc_dir.create()

        top = self.db.top_patch()
        # add new patch after the current topmost applied patch
        self.series.add_patches([patch], top)
        # "apply" patch
        self.db.add_patch(patch)

        # create patches/series files
        self.series.save()
        # create .pc/.version and .pc/applied-patches files
        self.db.save()

        self.patch_created(patch)
Esempio n. 14
0
    def import_patch(self, patch_name, new_name=None):
        """ Import patch into the patch queue
        The patch is inserted after the current top applied patch
        """
        if new_name:
            dir_name = os.path.dirname(new_name)
            name = os.path.basename(new_name)
            dest_dir = self.quilt_patches + Directory(dir_name)
            dest_dir.create()
        else:
            name = os.path.basename(patch_name)
            dest_dir = self.quilt_patches

        patch_file = File(patch_name)
        dest_file = dest_dir + File(name)
        patch_file.copy(dest_file)
        self._import_patches([name])
Esempio n. 15
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)
Esempio n. 16
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)
Esempio n. 17
0
    def backup_files(self, src_dir, dest_dir, filenames, copy_empty=False):
        for filename in filenames:
            src_file = src_dir + File(filename)

            if not src_file.exists():
                continue
            if src_file.is_empty() and not copy_empty:
                continue
            self.backup_file(src_file, dest_dir)
Esempio n. 18
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()))
Esempio n. 19
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
Esempio n. 20
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")

        if refresh.exists():
            raise QuiltError("Patch %s needs to be refreshed" % \
                                  patch_name)

        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)
                refresh.delete_if_exists()
            except SubprocessError, e:
                refresh.touch()

                if not force:
                    patch = RollbackPatch(self.cwd, pc_dir)
                    patch.rollback()
                    patch.delete_backup()
                    raise QuiltError("Patch %s does not apply" % patch_name)
                else:
                    forced = True
Esempio n. 21
0
    def _unapply_patch(self, patch):
        self.unapplying(patch)

        patch_name = patch.get_name()
        pc_dir = self.quilt_pc + patch_name
        timestamp = pc_dir + File(".timestamp")
        timestamp.delete_if_exists()

        if pc_dir.is_empty():
            pc_dir.delete()
            self.empty_patch(patch)
        else:
            unpatch = RollbackPatch(self.cwd, pc_dir)
            unpatch.rollback()
            unpatch.delete_backup()

        self.db.remove_patch(patch)

        refresh = File(pc_dir.get_name() + "~refresh")
        refresh.delete_if_exists()

        self.unapplied_patch(patch)
Esempio n. 22
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()))
Esempio n. 23
0
    def get_header(self, patch_dir=None):
        """ Returns bytes """
        lines = []

        if patch_dir:
            file = patch_dir + File(self.get_name())
            name = file.get_name()
        else:
            name = self.get_name()
        with open(name, "rb") as f:
            for line in f:
                if line.startswith(b"---") or line.startswith(b"Index:"):
                    break
                lines.append(line)

        return b"".join(lines)
Esempio n. 24
0
    def rollback(self, keep=False):
        (dirs, files) = self.backup_dir.content()

        for dir in dirs:
            newdir = self.cwd + dir
            if not newdir.exists():
                newdir.create()

        for file in files:
            file = File(file)
            backup_file = self.backup_dir + file
            rollback_file = self.cwd + file

            if not keep:
                rollback_file.delete_if_exists()
            if not backup_file.is_empty():
                backup_file.copy(rollback_file)
Esempio n. 25
0
    def _apply_patch_temporary(self, tmpdir, file, patch):
        backup = Backup()
        backup_file = backup.backup_file(file, tmpdir)
        patch_file = self.quilt_patches + File(patch.get_name())

        if patch_file.exists() and not patch_file.is_empty():
            try:
                patch.run(
                    self.cwd,
                    self.quilt_patches.get_absdir(),
                    work_dir=tmpdir,
                    no_backup_if_mismatch=True,
                    remove_empty_files=True,
                    force=True,
                    quiet=True,
                    suppress_output=True,
                )
            except SubprocessError:
                pass  # Expected to fail if there are other files in patch
        return backup_file
Esempio n. 26
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)
Esempio n. 27
0
class Diff(object):
    """ Wrapper around the diff util
    """
    @FileParam(["left", "right"])
    def __init__(self, left, right):
        """ left points to the first file and right to the second file
        """
        self.left = left
        if not self.left.exists():
            self.left = File("/dev/null")

        self.right = right
        if not self.right.exists():
            self.right = File("/dev/null")

    def run(self,
            cwd,
            left_label=None,
            right_label=None,
            unified=True,
            fd=None):
        cmd = ["diff"]

        if unified:
            cmd.append("-u")

        if left_label:
            cmd.append("--label")
            cmd.append(left_label)

        if right_label:
            if not left_label:
                cmd.append("--label")
                cmd.append(self.right.get_name())
            cmd.append("--label")
            cmd.append(right_label)

        cmd.append(self.left.get_name())
        cmd.append(self.right.get_name())

        try:
            Process(cmd).run(cwd=cwd, stdout=fd)
        except SubprocessError as e:
            if e.get_returncode() > 1:
                raise e

    def equal(self, cwd):
        """ Returns True if left and right are equal
        """
        cmd = ["diff"]
        cmd.append("-q")
        cmd.append(self.left.get_name())
        cmd.append(self.right.get_name())

        try:
            Process(cmd).run(cwd=cwd, suppress_output=True)
        except SubprocessError as e:
            if e.get_returncode() == 1:
                return False
            else:
                raise e
        return True