Example #1
0
def generate_ifdefined(all_patches):
    """Update autogenerated ifdefined patches, which can be used to selectively disable features at compile time."""
    enabled_patches = dict([(i, patch) for i, patch in all_patches.iteritems()
                            if not patch.disabled])

    for i, patch in enabled_patches.iteritems():
        if patch.ifdefined is None:
            continue

        filename = os.path.join(patch.directory, config.path_IfDefined)
        with open(filename, "wb") as fp:
            fp.write("From: Wine Staging Team <*****@*****.**>\n")
            fp.write("Subject: Autogenerated #ifdef patch for %s.\n" %
                     patch.name)
            fp.write("\n")

            depends = resolve_dependencies(enabled_patches, i)
            for f in patch.modified_files:

                # Reconstruct the state after applying the dependencies
                original = get_wine_file(f)
                for _, (_, p) in select_patches(enabled_patches, depends,
                                                f).iteritems():
                    original = patchutils.apply_patch(original, p, fuzz=0)

                # Now apply the main patch
                p = extract_patch(patch, f)[1]
                patched = patchutils.apply_patch(original, p, fuzz=0)

                # Now get the diff between both
                diff = patchutils.generate_ifdef_patch(original,
                                                       patched,
                                                       ifdef=patch.ifdefined)
                if diff is not None:
                    fp.write("diff --git a/%s b/%s\n" % (f, f))
                    fp.write("--- a/%s\n" % f)
                    fp.write("+++ b/%s\n" % f)
                    while True:
                        buf = diff.read(16384)
                        if buf == "": break
                        fp.write(buf)
                    diff.close()

            # Close the file
            fp.close()

        # Add changes to git
        subprocess.call(["git", "add", filename])

        # Add the autogenerated file as a last patch
        patch.files.append(os.path.basename(filename))
        for p in patchutils.read_patch(filename):
            assert p.modified_file in patch.modified_files
            patch.patches.append(p)
Example #2
0
def generate_ifdefined(all_patches):
    """Update autogenerated ifdefined patches, which can be used to selectively disable features at compile time."""
    enabled_patches = dict([(i, patch) for i, patch in all_patches.iteritems() if not patch.disabled])

    for i, patch in enabled_patches.iteritems():
        if patch.ifdefined is None:
            continue

        filename = os.path.join(patch.directory, config.path_IfDefined)
        with open(filename, "wb") as fp:
            fp.write("From: Wine Staging Team <*****@*****.**>\n")
            fp.write("Subject: Autogenerated #ifdef patch for %s.\n" % patch.name)
            fp.write("\n")

            depends = resolve_dependencies(enabled_patches, i)
            for f in patch.modified_files:

                # Reconstruct the state after applying the dependencies
                original = get_wine_file(f)
                for _, (_, p) in select_patches(enabled_patches, depends, f).iteritems():
                    original = patchutils.apply_patch(original, p, fuzz=0)

                # Now apply the main patch
                p = extract_patch(patch, f)[1]
                patched = patchutils.apply_patch(original, p, fuzz=0)

                # Now get the diff between both
                diff = patchutils.generate_ifdef_patch(original, patched, ifdef=patch.ifdefined)
                if diff is not None:
                    fp.write("diff --git a/%s b/%s\n" % (f, f))
                    fp.write("--- a/%s\n" % f)
                    fp.write("+++ b/%s\n" % f)
                    while True:
                        buf = diff.read(16384)
                        if buf == "": break
                        fp.write(buf)
                    diff.close()

            # Close the file
            fp.close()

        # Add changes to git
        subprocess.call(["git", "add", filename])

        # Add the autogenerated file as a last patch
        patch.files.append(os.path.basename(filename))
        for p in patchutils.read_patch(filename):
            assert p.modified_file in patch.modified_files
            patch.patches.append(p)
Example #3
0
def read_patchset(revision=None):
    """Read information about all patchsets for a specific revision."""
    unique_id = itertools.count()
    all_patches = {}
    name_to_id = {}

    # Read in sorted order (to ensure created Makefile doesn't change too much)
    for name, directory in sorted(
            enum_directories(revision, config.path_patches)):
        patch = PatchSet(name, directory)

        if revision is None:

            # If its the latest revision, then request additional information
            if not os.path.isdir(directory):
                raise RuntimeError("Unable to open directory %s" % directory)

            # Enumerate .patch files in the given directory, enumerate individual patches and affected files
            for f in sorted(os.listdir(directory)):
                if not re.match("^[0-9]{4}-.*\\.patch$", f):
                    continue
                if f.startswith(config.path_IfDefined):
                    continue
                if not os.path.isfile(os.path.join(directory, f)):
                    continue
                patch.files.append(f)
                for p in patchutils.read_patch(os.path.join(directory, f)):
                    patch.modified_files.add(p.modified_file)
                    patch.patches.append(p)

            # No single patch within this directory, ignore it
            if len(patch.patches) == 0:
                del patch
                continue

        i = next(unique_id)
        all_patches[i] = patch
        name_to_id[name] = i

    # Now read the definition files in a second step
    for i, patch in all_patches.iteritems():
        try:
            patch.depends, patch.fixes, patch.disabled, patch.ifdefined = \
                read_definition(revision, os.path.join(config.path_patches, patch.name), name_to_id)
        except IOError:
            patch.depends, patch.fixes, patch.disabled, patch.ifdefined = set(
            ), [], False, None

    return all_patches
def generate_ifdefined(all_patches, skip_checks=False):
    """Update autogenerated ifdefined patches, which can be used to selectively disable features at compile time."""
    for i, patch in all_patches.iteritems():
        if patch.ifdefined is None:
            continue
        if patch.disabled:
            continue

        filename = os.path.join(patch.directory, config.path_IfDefined)
        headers = { 'author': "Wine Staging Team",
                    'email': "*****@*****.**",
                    'subject': "Autogenerated #ifdef patch for %s." % patch.name }

        if skip_checks:
            patch.files = [os.path.basename(filename)]
            continue

        with open(filename, "wb") as fp:
            fp.write("From: %s <%s>\n" % (headers['author'], headers['email']))
            fp.write("Subject: %s\n" % headers['subject'])
            fp.write("\n")
            fp.write("Based on patches by:\n")
            for author, email in sorted(set([(p.patch_author, p.patch_email) for p in patch.patches])):
                fp.write("    %s <%s>\n" % (author, email))
            fp.write("\n")

            depends = resolve_dependencies(all_patches, i)
            for f in sorted(patch.modified_files):

                # Reconstruct the state after applying the dependencies
                original = get_wine_file(f)
                selected_patches = select_patches(all_patches, depends, f)
                failed = []

                try:
                    for j in depends:
                        failed.append(j)
                        original = patchutils.apply_patch(original, selected_patches[j][1], fuzz=0)
                except patchutils.PatchApplyError:
                    raise PatchUpdaterError("Changes to file %s don't apply: %s" %
                                            (f, ", ".join([all_patches[j].name for j in failed])))

                # Now apply the main patch
                p = extract_patch(patch, f)[1]

                try:
                    failed.append(i)
                    patched = patchutils.apply_patch(original, p, fuzz=0)
                except patchutils.PatchApplyError:
                    raise PatchUpdaterError("Changes to file %s don't apply: %s" %
                                            (f, ", ".join([all_patches[j].name for j in failed])))

                # Now get the diff between both
                diff = patchutils.generate_ifdef_patch(original, patched, ifdef=patch.ifdefined)
                if diff is not None:
                    fp.write("diff --git a/%s b/%s\n" % (f, f))
                    fp.write("--- a/%s\n" % f)
                    fp.write("+++ b/%s\n" % f)
                    while True:
                        buf = diff.read(16384)
                        if buf == "": break
                        fp.write(buf)
                    diff.close()

            # Close the file
            fp.close()

        # Add changes to git
        subprocess.call(["git", "add", filename])

        # Add the autogenerated file as a last patch
        patch.files = [os.path.basename(filename)]
        for p in patch.patches:
            p.filename      = None
            p.modified_file = None
        for p in patchutils.read_patch(filename):
            assert p.modified_file in patch.modified_files
            p.patch_author  = None
            patch.patches.append(p)
def load_patchsets():
    """Read information about all patchsets."""
    unique_id   = itertools.count()
    all_patches = {}
    name_to_id  = {}

    for name, directory in enum_patchsets(config.path_patches):
        patch = PatchSet(name, directory)

        # Load the definition file
        try:
            with open(os.path.join(directory, "definition")) as fp:
                for line in fp:
                    if line.startswith("#"):
                        continue
                    tmp = line.split(":", 1)
                    if len(tmp) != 2:
                        continue
                    patch.config.append((tmp[0].lower(), tmp[1].strip()))
        except IOError:
            pass

        # Enumerate .patch files in the given directory, enumerate individual patches and affected files
        for f in sorted(os.listdir(directory)):
            if not re.match("^[0-9]{4}-.*\\.patch$", f):
                continue
            if f.startswith(config.path_IfDefined):
                continue
            if ("exclude", f) in patch.config:
                continue
            if not os.path.isfile(os.path.join(directory, f)):
                continue
            patch.files.append(f)
            for p in patchutils.read_patch(os.path.join(directory, f)):
                patch.modified_files.add(p.modified_file)
                patch.patches.append(p)

        # No single patch within this directory, ignore it
        if len(patch.patches) == 0:
            del patch
            continue

        i = next(unique_id)
        all_patches[i]   = patch
        name_to_id[name] = i

    # Now read the definition files in a second step
    for i, patch in all_patches.iteritems():
        for key, val in patch.config:
            if key == "depends":
                if not name_to_id.has_key(val):
                    raise PatchUpdaterError("Definition file for %s references unknown dependency %s" % (patch.name, val))
                patch.depends.add(name_to_id[val])

            elif key == "apply-after":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([fnmatch.fnmatch(f, val) for f in other_patch.modified_files]):
                        patch.auto_depends.add(j)

            elif key == "apply-before":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([fnmatch.fnmatch(f, val) for f in other_patch.modified_files]):
                        other_patch.auto_depends.add(i)

            elif key == "fixes":
                r = re.match("^\\[ *(!)? *([0-9]+) *\\](.*)$", val)
                if r:
                    sync  = (r.group(1) != "!")
                    bugid = int(r.group(2))
                    patch.fixes.append((sync, bugid, r.group(3).strip()))
                    continue
                patch.fixes.append((False, None, val))

            elif key == "disabled":
                patch.disabled = _parse_int(val)

            elif key == "exclude":
                pass # Already processed above

            elif key == "ifdefined":
                patch.ifdefined = val

            else:
                print "WARNING: Ignoring unknown command in definition file for %s: %s" % (patch.name, line)

    # Filter autodepends on disabled patchsets
    for i, patch in all_patches.iteritems():
        patch.auto_depends = set([j for j in patch.auto_depends if not all_patches[j].disabled])

    return all_patches
Example #6
0
def generate_ifdefined(all_patches, skip_checks=False):
    """Update autogenerated ifdefined patches, which can be used to selectively disable features at compile time."""
    enabled_patches = dict([(i, patch) for i, patch in all_patches.iteritems() if not patch.disabled])

    for i, patch in enabled_patches.iteritems():
        if patch.ifdefined is None:
            continue

        filename = os.path.join(patch.directory, config.path_IfDefined)
        headers = { 'author': "Wine Staging Team",
                    'email': "*****@*****.**",
                    'subject': "Autogenerated #ifdef patch for %s." % patch.name }

        if skip_checks:
            patch.files = [os.path.basename(filename)]
            continue

        with open(filename, "wb") as fp:
            fp.write("From: %s <%s>\n" % (headers['author'], headers['email']))
            fp.write("Subject: %s\n" % headers['subject'])
            fp.write("\n")
            fp.write("Based on patches by:\n")
            for author, email in sorted(set([(p.patch_author, p.patch_email) for p in patch.patches])):
                fp.write("    %s <%s>\n" % (author, email))
            fp.write("\n")

            depends = resolve_dependencies(enabled_patches, i)
            for f in sorted(patch.modified_files):

                # Reconstruct the state after applying the dependencies
                original = get_wine_file(f)
                selected_patches = select_patches(enabled_patches, depends, f)
                failed = []

                try:
                    for j in depends:
                        failed.append(j)
                        original = patchutils.apply_patch(original, selected_patches[j][1], fuzz=0)
                except patchutils.PatchApplyError:
                    raise PatchUpdaterError("Changes to file %s don't apply: %s" %
                                            (f, ", ".join([all_patches[j].name for j in failed])))

                # Now apply the main patch
                p = extract_patch(patch, f)[1]

                try:
                    failed.append(i)
                    patched = patchutils.apply_patch(original, p, fuzz=0)
                except patchutils.PatchApplyError:
                    raise PatchUpdaterError("Changes to file %s don't apply: %s" %
                                            (f, ", ".join([all_patches[j].name for j in failed])))

                # Now get the diff between both
                diff = patchutils.generate_ifdef_patch(original, patched, ifdef=patch.ifdefined)
                if diff is not None:
                    fp.write("diff --git a/%s b/%s\n" % (f, f))
                    fp.write("--- a/%s\n" % f)
                    fp.write("+++ b/%s\n" % f)
                    while True:
                        buf = diff.read(16384)
                        if buf == "": break
                        fp.write(buf)
                    diff.close()

            # Close the file
            fp.close()

        # Add changes to git
        subprocess.call(["git", "add", filename])

        # Add the autogenerated file as a last patch
        patch.files = [os.path.basename(filename)]
        for p in patch.patches:
            p.filename      = None
            p.modified_file = None
        for p in patchutils.read_patch(filename):
            assert p.modified_file in patch.modified_files
            p.patch_author  = None
            patch.patches.append(p)
Example #7
0
def load_patchsets():
    """Read information about all patchsets."""
    unique_id   = itertools.count()
    all_patches = {}
    name_to_id  = {}
    categories  = {}

    for name, directory in enum_patchsets(config.path_patches):
        patch = PatchSet(name, directory)

        # Enumerate .patch files in the given directory, enumerate individual patches and affected files
        for f in sorted(os.listdir(directory)):
            if not re.match("^[0-9]{4}-.*\\.patch$", f):
                continue
            if f.startswith(config.path_IfDefined):
                continue
            if not os.path.isfile(os.path.join(directory, f)):
                continue
            patch.files.append(f)
            for p in patchutils.read_patch(os.path.join(directory, f)):
                patch.modified_files.add(p.modified_file)
                patch.patches.append(p)

        # No single patch within this directory, ignore it
        if len(patch.patches) == 0:
            del patch
            continue

        i = next(unique_id)
        all_patches[i]   = patch
        name_to_id[name] = i

    # Now read the definition files in a second step
    for i, patch in all_patches.iteritems():
        filename = os.path.join(os.path.join(config.path_patches, patch.name), "definition")
        try:
            with open(filename) as fp:
                content = fp.read()
        except IOError:
            continue # Skip this definition file

        for line in content.split("\n"):
            if line.startswith("#"):
                continue
            tmp = line.split(":", 1)
            if len(tmp) != 2:
                continue

            key, val = tmp[0].lower(), tmp[1].strip()
            if key == "depends":
                if not name_to_id.has_key(val):
                    raise PatchUpdaterError("Definition file %s references unknown dependency %s" % (filename, val))
                patch.depends.add(name_to_id[val])

            elif key == "apply-after":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([fnmatch.fnmatch(f, val) for f in other_patch.modified_files]):
                        patch.auto_depends.add(j)

            elif key == "apply-before":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([fnmatch.fnmatch(f, val) for f in other_patch.modified_files]):
                        other_patch.auto_depends.add(i)

            elif key == "category":
                val = "category-%s" % val
                if name_to_id.has_key(val):
                    raise PatchUpdaterError("Category name in definition file %s collides with patchset %s" % (filename, val))
                patch.categories.append(val)

            elif key == "fixes":
                r = re.match("^\\[ *(!)? *([0-9]+) *\\](.*)$", val)
                if r:
                    sync  = (r.group(1) != "!")
                    bugid = int(r.group(2))
                    patch.fixes.append((sync, bugid, r.group(3).strip()))
                    continue
                patch.fixes.append((False, None, val))

            elif key == "disabled":
                patch.disabled = _parse_int(val)

            elif key == "ifdefined":
                patch.ifdefined = val

            else:
                print "WARNING: Ignoring unknown command in definition file %s: %s" % (filename, line)

        # If patch is not disabled then finally add it to the category
        if patch.disabled:
            continue

        for category in patch.categories:
            if not categories.has_key(category):
                categories[category] = set()
            categories[category].add(i)

    # Filter autodepends on disabled patchsets
    for i, patch in all_patches.iteritems():
        patch.auto_depends = set([j for j in patch.auto_depends if not all_patches[j].disabled])

    # Add virtual targets for all the categories
    for category, indices in categories.iteritems():
        patch = PatchSet(category, directory)
        patch.is_category = True
        patch.depends = indices

        i = next(unique_id)
        all_patches[i] = patch
        name_to_id[name] = i

    return all_patches
Example #8
0
def read_patchset(revision = None):
    """Read information about all patchsets for a specific revision."""
    unique_id   = itertools.count()
    all_patches = {}
    name_to_id  = {}
    all_bugids  = set()
    categories  = {}

    # Read in sorted order (to ensure created Makefile doesn't change too much)
    for name, directory in sorted(enum_directories(revision, config.path_patches)):
        patch = PatchSet(name, directory)

        if revision is None:

            # If its the latest revision, then request additional information
            if not os.path.isdir(directory):
                raise RuntimeError("Unable to open directory %s" % directory)

            # Enumerate .patch files in the given directory, enumerate individual patches and affected files
            for f in sorted(os.listdir(directory)):
                if not re.match("^[0-9]{4}-.*\\.patch$", f):
                    continue
                if f.startswith(config.path_IfDefined):
                    continue
                if not os.path.isfile(os.path.join(directory, f)):
                    continue
                patch.files.append(f)
                for p in patchutils.read_patch(os.path.join(directory, f)):
                    patch.modified_files.add(p.modified_file)
                    patch.patches.append(p)

            # No single patch within this directory, ignore it
            if len(patch.patches) == 0:
                del patch
                continue

        i = next(unique_id)
        all_patches[i]   = patch
        name_to_id[name] = i

    # Now read the definition files in a second step
    for i, patch in all_patches.iteritems():
        try:
            filename = os.path.join(os.path.join(config.path_patches, patch.name), "definition")
            if revision is None:
                with open(filename) as fp:
                    content = fp.read()
            else:
                filename = "%s:%s" % (revision, filename)
                content = subprocess.check_output(["git", "show", filename], stderr=_devnull)
        except (IOError, subprocess.CalledProcessError):
            continue # Skip this definition file

        for line in content.split("\n"):
            if line.startswith("#"):
                continue
            tmp = line.split(":", 1)
            if len(tmp) != 2:
                continue

            key, val = tmp[0].lower(), tmp[1].strip()
            if key == "depends":
                if not name_to_id.has_key(val):
                    raise PatchUpdaterError("Definition file %s references unknown dependency %s" % (filename, val))
                patch.depends.add(name_to_id[val])

            elif key == "apply-after":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([fnmatch.fnmatch(f, val) for f in other_patch.modified_files]):
                        patch.auto_depends.add(j)

            elif key == "category":
                val = "category-%s" % val
                if name_to_id.has_key(val):
                    raise PatchUpdaterError("Category name in definition file %s collides with patchset %s" % (filename, val))
                patch.categories.append(val)

            elif key == "fixes":
                r = re.match("^[0-9]+$", val)
                if r:
                    bugid = int(val)
                    patch.fixes.append((bugid, None))
                    all_bugids.add(bugid)
                    continue
                r = re.match("^\\[ *([0-9]+) *\\](.*)$", val)
                if r:
                    bugid = int(r.group(1))
                    patch.fixes.append((bugid, r.group(2).strip()))
                    all_bugids.add(bugid)
                    continue
                patch.fixes.append((None, val))

            elif key == "disabled":
                patch.disabled = _parse_int(val)

            elif key == "ifdefined":
                patch.ifdefined = val

            elif revision is None:
                print "WARNING: Ignoring unknown command in definition file %s: %s" % (filename, line)

        # If patch is not disabled then finally add it to the category
        if not patch.disabled:
            for category in patch.categories:
                if not categories.has_key(category):
                    categories[category] = set()
                categories[category].add(i)


    # Add virtual targets for all the categories
    for category, indices in categories.iteritems():
        patch = PatchSet(category, directory)
        patch.is_category = True
        patch.depends = indices

        i = next(unique_id)
        all_patches[i] = patch
        name_to_id[name] = i

    # To simplify the task of keeping the bug list up-to-date, list all bugs
    # which might require attention.
    if revision is None:
        once = True
        for bugid, bug in sorted(_winebugs_query(all_bugids).items()):
            if bug['bug_status'] not in ["UNCONFIRMED", "NEW", "ASSIGNED", "REOPENED"]:
                if once:
                    print ""
                    print "WARNING: The following bugs might require attention:"
                    print ""
                    once = False
                print " #%d - \"%s\" - %s %s" % (bugid, bug['short_desc'], bug['bug_status'],
                                                 bug['resolution'] if bug['resolution'] else "")
        print ""

    return all_patches
Example #9
0
def read_patchset(revision=None):
    """Read information about all patchsets for a specific revision."""
    unique_id = itertools.count()
    all_patches = {}
    name_to_id = {}
    all_bugids = set()
    categories = {}

    # Read in sorted order (to ensure created Makefile doesn't change too much)
    for name, directory in sorted(
            enum_directories(revision, config.path_patches)):
        patch = PatchSet(name, directory)

        if revision is None:

            # If its the latest revision, then request additional information
            if not os.path.isdir(directory):
                raise RuntimeError("Unable to open directory %s" % directory)

            # Enumerate .patch files in the given directory, enumerate individual patches and affected files
            for f in sorted(os.listdir(directory)):
                if not re.match("^[0-9]{4}-.*\\.patch$", f):
                    continue
                if f.startswith(config.path_IfDefined):
                    continue
                if not os.path.isfile(os.path.join(directory, f)):
                    continue
                patch.files.append(f)
                for p in patchutils.read_patch(os.path.join(directory, f)):
                    patch.modified_files.add(p.modified_file)
                    patch.patches.append(p)

            # No single patch within this directory, ignore it
            if len(patch.patches) == 0:
                del patch
                continue

        i = next(unique_id)
        all_patches[i] = patch
        name_to_id[name] = i

    # Now read the definition files in a second step
    for i, patch in all_patches.iteritems():
        try:
            filename = os.path.join(
                os.path.join(config.path_patches, patch.name), "definition")
            if revision is None:
                with open(filename) as fp:
                    content = fp.read()
            else:
                filename = "%s:%s" % (revision, filename)
                content = subprocess.check_output(["git", "show", filename],
                                                  stderr=_devnull)
        except (IOError, subprocess.CalledProcessError):
            continue  # Skip this definition file

        for line in content.split("\n"):
            if line.startswith("#"):
                continue
            tmp = line.split(":", 1)
            if len(tmp) != 2:
                continue

            key, val = tmp[0].lower(), tmp[1].strip()
            if key == "depends":
                if not name_to_id.has_key(val):
                    raise PatchUpdaterError(
                        "Definition file %s references unknown dependency %s" %
                        (filename, val))
                patch.depends.add(name_to_id[val])

            elif key == "apply-after":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([
                            fnmatch.fnmatch(f, val)
                            for f in other_patch.modified_files
                    ]):
                        patch.auto_depends.add(j)

            elif key == "apply-before":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([
                            fnmatch.fnmatch(f, val)
                            for f in other_patch.modified_files
                    ]):
                        other_patch.auto_depends.add(i)

            elif key == "category":
                val = "category-%s" % val
                if name_to_id.has_key(val):
                    raise PatchUpdaterError(
                        "Category name in definition file %s collides with patchset %s"
                        % (filename, val))
                patch.categories.append(val)

            elif key == "fixes":
                r = re.match("^[0-9]+$", val)
                if r:
                    bugid = int(val)
                    patch.fixes.append((bugid, None))
                    all_bugids.add(bugid)
                    continue
                r = re.match("^\\[ *([0-9]+) *\\](.*)$", val)
                if r:
                    bugid = int(r.group(1))
                    patch.fixes.append((bugid, r.group(2).strip()))
                    all_bugids.add(bugid)
                    continue
                patch.fixes.append((None, val))

            elif key == "disabled":
                patch.disabled = _parse_int(val)

            elif key == "ifdefined":
                patch.ifdefined = val

            elif revision is None:
                print "WARNING: Ignoring unknown command in definition file %s: %s" % (
                    filename, line)

        # If patch is not disabled then finally add it to the category
        if not patch.disabled:
            for category in patch.categories:
                if not categories.has_key(category):
                    categories[category] = set()
                categories[category].add(i)

    # Add virtual targets for all the categories
    for category, indices in categories.iteritems():
        patch = PatchSet(category, directory)
        patch.is_category = True
        patch.depends = indices

        i = next(unique_id)
        all_patches[i] = patch
        name_to_id[name] = i

    # To simplify the task of keeping the bug list up-to-date, list all bugs
    # which might require attention.
    if revision is None:
        once = True
        for bugid, bug in sorted(_winebugs_query(all_bugids).items()):
            if bug['bug_status'] not in [
                    "UNCONFIRMED", "NEW", "ASSIGNED", "REOPENED"
            ]:
                if once:
                    print ""
                    print "WARNING: The following bugs might require attention:"
                    print ""
                    once = False
                print " #%d - \"%s\" - %s %s" % (
                    bugid, bug['short_desc'], bug['bug_status'],
                    bug['resolution'] if bug['resolution'] else "")
        print ""

    return all_patches
Example #10
0
def load_patchsets():
    """Read information about all patchsets."""
    unique_id = itertools.count()
    all_patches = {}
    name_to_id = {}
    categories = {}

    for name, directory in enum_patchsets(config.path_patches):
        patch = PatchSet(name, directory)

        # Enumerate .patch files in the given directory, enumerate individual patches and affected files
        for f in sorted(os.listdir(directory)):
            if not re.match("^[0-9]{4}-.*\\.patch$", f):
                continue
            if f.startswith(config.path_IfDefined):
                continue
            if not os.path.isfile(os.path.join(directory, f)):
                continue
            patch.files.append(f)
            for p in patchutils.read_patch(os.path.join(directory, f)):
                patch.modified_files.add(p.modified_file)
                patch.patches.append(p)

        # No single patch within this directory, ignore it
        if len(patch.patches) == 0:
            del patch
            continue

        i = next(unique_id)
        all_patches[i] = patch
        name_to_id[name] = i

    # Now read the definition files in a second step
    for i, patch in all_patches.iteritems():
        filename = os.path.join(os.path.join(config.path_patches, patch.name),
                                "definition")
        try:
            with open(filename) as fp:
                content = fp.read()
        except IOError:
            continue  # Skip this definition file

        for line in content.split("\n"):
            if line.startswith("#"):
                continue
            tmp = line.split(":", 1)
            if len(tmp) != 2:
                continue

            key, val = tmp[0].lower(), tmp[1].strip()
            if key == "depends":
                if not name_to_id.has_key(val):
                    raise PatchUpdaterError(
                        "Definition file %s references unknown dependency %s" %
                        (filename, val))
                patch.depends.add(name_to_id[val])

            elif key == "apply-after":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([
                            fnmatch.fnmatch(f, val)
                            for f in other_patch.modified_files
                    ]):
                        patch.auto_depends.add(j)

            elif key == "apply-before":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([
                            fnmatch.fnmatch(f, val)
                            for f in other_patch.modified_files
                    ]):
                        other_patch.auto_depends.add(i)

            elif key == "category":
                val = "category-%s" % val
                if name_to_id.has_key(val):
                    raise PatchUpdaterError(
                        "Category name in definition file %s collides with patchset %s"
                        % (filename, val))
                patch.categories.append(val)

            elif key == "fixes":
                r = re.match("^\\[ *(!)? *([0-9]+) *\\](.*)$", val)
                if r:
                    sync = (r.group(1) != "!")
                    bugid = int(r.group(2))
                    patch.fixes.append((sync, bugid, r.group(3).strip()))
                    continue
                patch.fixes.append((False, None, val))

            elif key == "disabled":
                patch.disabled = _parse_int(val)

            elif key == "ifdefined":
                patch.ifdefined = val

            else:
                print "WARNING: Ignoring unknown command in definition file %s: %s" % (
                    filename, line)

        # If patch is not disabled then finally add it to the category
        if patch.disabled:
            continue

        for category in patch.categories:
            if not categories.has_key(category):
                categories[category] = set()
            categories[category].add(i)

    # Filter autodepends on disabled patchsets
    for i, patch in all_patches.iteritems():
        patch.auto_depends = set(
            [j for j in patch.auto_depends if not all_patches[j].disabled])

    # Add virtual targets for all the categories
    for category, indices in categories.iteritems():
        patch = PatchSet(category, directory)
        patch.is_category = True
        patch.depends = indices

        i = next(unique_id)
        all_patches[i] = patch
        name_to_id[name] = i

    return all_patches
Example #11
0
def load_patchsets():
    """Read information about all patchsets."""
    unique_id   = itertools.count()
    all_patches = {}
    name_to_id  = {}

    for name, directory in enum_patchsets(config.path_patches):
        patch = PatchSet(name, directory)

        # Load the definition file
        try:
            with open(os.path.join(directory, "definition")) as fp:
                for line in fp:
                    if line.startswith("#"):
                        continue
                    tmp = line.split(":", 1)
                    if len(tmp) != 2:
                        continue
                    patch.config.append((tmp[0].lower(), tmp[1].strip()))
        except IOError:
            pass

        # Enumerate .patch files in the given directory, enumerate individual patches and affected files
        for f in sorted(os.listdir(directory)):
            if not re.match("^[0-9]{4}-.*\\.patch$", f):
                continue
            if f.startswith(config.path_IfDefined):
                continue
            if ("exclude", f) in patch.config:
                continue
            if not os.path.isfile(os.path.join(directory, f)):
                continue
            patch.files.append(f)
            for p in patchutils.read_patch(os.path.join(directory, f)):
                patch.modified_files.add(p.modified_file)
                patch.patches.append(p)

        # No single patch within this directory, ignore it
        if len(patch.patches) == 0:
            del patch
            continue

        i = next(unique_id)
        all_patches[i]   = patch
        name_to_id[name] = i

    # Now read the definition files in a second step
    for i, patch in all_patches.iteritems():
        for key, val in patch.config:
            if key == "depends":
                if not name_to_id.has_key(val):
                    raise PatchUpdaterError("Definition file for %s references unknown dependency %s" % (patch.name, val))
                patch.depends.add(name_to_id[val])

            elif key == "apply-after":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([fnmatch.fnmatch(f, val) for f in other_patch.modified_files]):
                        patch.auto_depends.add(j)

            elif key == "apply-before":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([fnmatch.fnmatch(f, val) for f in other_patch.modified_files]):
                        other_patch.auto_depends.add(i)

            elif key == "fixes":
                r = re.match("^\\[ *(!)? *([0-9]+) *\\](.*)$", val)
                if r:
                    sync  = (r.group(1) != "!")
                    bugid = int(r.group(2))
                    patch.fixes.append((sync, bugid, r.group(3).strip()))
                    continue
                patch.fixes.append((False, None, val))

            elif key == "disabled":
                patch.disabled = _parse_int(val)

            elif key == "exclude":
                pass # Already processed above

            elif key == "ifdefined":
                patch.ifdefined = val

            else:
                print "WARNING: Ignoring unknown command in definition file for %s: %s" % (patch.name, line)

    # Filter autodepends on disabled patchsets
    for i, patch in all_patches.iteritems():
        patch.auto_depends = set([j for j in patch.auto_depends if not all_patches[j].disabled])

    return all_patches
Example #12
0
def read_patchset(revision=None):
    """Read information about all patchsets for a specific revision."""
    unique_id = itertools.count()
    all_patches = {}
    name_to_id = {}

    # Read in sorted order (to ensure created Makefile doesn't change too much)
    for name, directory in sorted(
            enum_directories(revision, config.path_patches)):
        patch = PatchSet(name, directory)

        if revision is None:

            # If its the latest revision, then request additional information
            if not os.path.isdir(directory):
                raise RuntimeError("Unable to open directory %s" % directory)

            # Enumerate .patch files in the given directory, enumerate individual patches and affected files
            for f in sorted(os.listdir(directory)):
                if not re.match("^[0-9]{4}-.*\\.patch$", f):
                    continue
                if f.startswith(config.path_IfDefined):
                    continue
                if not os.path.isfile(os.path.join(directory, f)):
                    continue
                patch.files.append(f)
                for p in patchutils.read_patch(os.path.join(directory, f)):
                    patch.modified_files.add(p.modified_file)
                    patch.patches.append(p)

            # No single patch within this directory, ignore it
            if len(patch.patches) == 0:
                del patch
                continue

        i = next(unique_id)
        all_patches[i] = patch
        name_to_id[name] = i

    # Now read the definition files in a second step
    for i, patch in all_patches.iteritems():
        try:
            filename = os.path.join(
                os.path.join(config.path_patches, patch.name), "definition")
            if revision is None:
                with open(filename) as fp:
                    content = fp.read()
            else:
                filename = "%s:%s" % (revision, filename)
                content = subprocess.check_output(["git", "show", filename],
                                                  stderr=_devnull)
        except (IOError, subprocess.CalledProcessError):
            continue  # Skip this definition file

        for line in content.split("\n"):
            if line.startswith("#"):
                continue
            tmp = line.split(":", 1)
            if len(tmp) != 2:
                continue

            key, val = tmp[0].lower(), tmp[1].strip()
            if key == "depends":
                if not name_to_id.has_key(val):
                    raise PatchUpdaterError(
                        "Definition file %s references unknown dependency %s" %
                        (filename, val))
                patch.depends.add(name_to_id[val])

            elif key == "apply-after":
                for j, other_patch in all_patches.iteritems():
                    if i != j and any([
                            fnmatch.fnmatch(f, val)
                            for f in other_patch.modified_files
                    ]):
                        patch.auto_depends.add(j)

            elif key == "fixes":
                r = re.match("^[0-9]+$", val)
                if r:
                    patch.fixes.append((int(val), None))
                    continue
                r = re.match("^\\[ *([0-9]+) *\\](.*)$", val)
                if r:
                    patch.fixes.append((int(r.group(1)), r.group(2).strip()))
                    continue
                patch.fixes.append((None, val))

            elif key == "disabled":
                patch.disabled = _parse_int(val)

            elif key == "ifdefined":
                patch.ifdefined = val

            elif revision is None:
                print "WARNING: Ignoring unknown command in definition file %s: %s" % (
                    filename, line)

    return all_patches