~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Copyright 2004 Canonical Ltd.  All rights reserved.
"""Check source tree against the policy for using arch-tag.

Run with the argument 'check' to check the tree against allowed-tags.txt

You can also call the is_tree_good() method to run a check in-process from
Python code.
"""

__metaclass__ = type

import os
import sys
import sets

def get_actual_tags():
    """Returns a mapping of tag->filename for all files in the tree."""
    tagdict = {}
    stdin, out, err = os.popen3("baz inventory -s --ids")
    dataout = out.readlines()
    for line in dataout:
        filename, tag = line.split()
        if tag.startswith('i_'):
            tagdict[tag[2:]] = filename
    return tagdict

def is_tree_good():
    if not os.path.exists('allowed-tags.txt'):
        return False
    allowed_tags = read_allowed_tags()
    actual_tags = get_actual_tags()
    return check_tags_dicts(allowed_tags, actual_tags)

def check_tags_dicts(allowed_tags, actual_tags):
    allowed_tags_set = sets.Set(allowed_tags.keys())
    actual_tags_set = sets.Set(actual_tags.keys())
    removed_tags = allowed_tags_set - actual_tags_set
    added_tags = actual_tags_set - allowed_tags_set
    changed_tags = sets.Set(
        [tag for tag, value in
            sets.Set(allowed_tags.items()) - sets.Set(actual_tags.items())
        ]) - removed_tags
    print
    print "Total number of files with implicit ids: %s" % len(actual_tags)
    print
    if added_tags:
        print "New tags have been added:"
        for tag in added_tags:
            print tag, actual_tags[tag]
        print "This will prevent merging into rocketfuel."
    if removed_tags:
        print "Tags have been removed:"
        for tag in removed_tags:
            print tag, allowed_tags[tag]
        if not added_tags:
            print "You should re-generate the allowed-tags file."
    if changed_tags:
        print "Tags have been changed:"
        for tag in changed_tags:
            print tag, allowed_tags[tag], '->', actual_tags[tag]
        if not added_tags:
            print "You need to re-generate the allowed-tags file."

    if not added_tags | removed_tags | changed_tags:
        print "There were no changed tags."

    if added_tags or changed_tags:
        return False
    else:
        return True

def read_allowed_tags():
    tagdict = {}
    for line in open('allowed-tags.txt').readlines():
        filename, tag = line.split()
        tagdict[tag] = filename
    return tagdict

def create_allowed_tags():
    """Create a file called allowed-tags.txt containing lines of the form

      filename archtag

    sorted by filename.
    """
    print "Go away. We do not want to add any more tagged files. You should"
    print "only be deleting tags from files, not adding any new ones. If"
    print "you have deleted a tag from a file, then you can delete the"
    print "relevant line from allowed-tags.txt"
    tags = get_actual_tags().items()

    # Schwartz transform to sort on filename.
    L = [(item[1], item) for item in tags]
    L.sort()
    tags = [item for sortkey, item in L]

    allowed_tags_file = open('allowed-tags.txt', 'w')
    for tag, filename in tags:
        print >>allowed_tags_file, '%s %s' % (filename, tag)
    allowed_tags_file.close()
    print "created allowed-tags.txt"

if __name__ == '__main__':
    args = sys.argv[1:]
    if len(args) == 1:
        command = args[0].lower()
        if command == 'create':
            create_allowed_tags()
            sys.exit(0)
        elif command == 'check':
            if is_tree_good():
                sys.exit(0)
            else:
                sys.exit(1)
    print "usage: python checkarchtag.py [ create | check ]"
    sys.exit(1)