/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to patches/meta-data-in-inventory.patch

  • Committer: John Arbash Meinel
  • Date: 2010-01-12 22:51:31 UTC
  • mto: This revision was merged to the branch mainline in revision 4955.
  • Revision ID: john@arbash-meinel.com-20100112225131-he8h411p6aeeb947
Delay grabbing an output stream until we actually go to show a diff.

This makes the test suite happy, but it also seems to be reasonable.
If we aren't going to write anything, we don't need to hold an
output stream open.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
*** modified file 'bzrlib/commands.py'
2
 
--- bzrlib/commands.py 
3
 
+++ bzrlib/commands.py 
4
 
@@ -1175,7 +1175,68 @@
5
 
         b = Branch('.')
6
 
         statcache.update_cache(b.base, b.read_working_inventory())
7
 
 
8
 
-
9
 
+class cmd_meta(Command):
10
 
+    """Get or set the meta information properties about a file.
11
 
+
12
 
+    bzr meta FILENAME # Display all meta information
13
 
+    bzr meta FILENAME prop # Display the value of meta-info named prop, return error if not found
14
 
+    bzr meta FILENAME --set prop value # Set the value of prop to value
15
 
+    echo "the value" | bzr meta FILENAME --set prop # Set the value to whatever is read from stdin
16
 
+    bzr meta FILENAME --unset prop # Remove the property
17
 
+
18
 
+    bzr meta FILENAME --revision=10 # Display the meta information for a given revision
19
 
+        (Not supported yet)
20
 
+    """
21
 
+    hidden = True
22
 
+    takes_args = ['filename', 'property?', 'value?']
23
 
+    takes_options = ['revision', 'set', 'unset']
24
 
+
25
 
+    def run(self, filename, property=None, value=None, revision=None, set=False, unset=False):
26
 
+        if isinstance(revision, list) and len(revision) > 1:
27
 
+            raise BzrCommandError('bzr meta takes at most 1 revision.')
28
 
+        if revision is not None and (set or unset):
29
 
+            raise BzrCommandError('Cannot set/unset meta information in an old version.')
30
 
+        if set and unset:
31
 
+            raise BzrCommandError('Cannot set and unset at the same time')
32
 
+        if not set and value:
33
 
+            raise BzrCommandError('You must supply --set if you want to set the value of a property.')
34
 
+
35
 
+        b = Branch(filename)
36
 
+        inv = b.inventory
37
 
+        file_id = inv.path2id(b.relpath(filename))
38
 
+        inv_entry = inv[file_id]
39
 
+        if not property:
40
 
+            meta = inv_entry.meta
41
 
+            if meta: # Not having meta is the same as having an empty meta
42
 
+                keys = meta.properties.keys()
43
 
+                keys.sort()
44
 
+                # The output really needs to be parseable
45
 
+                for key in keys:
46
 
+                    print '%s: %r' % (key, meta.properties[key])
47
 
+        else:
48
 
+            meta = inv_entry.meta
49
 
+            if set:
50
 
+                if value is None:
51
 
+                    value = sys.stdin.read()
52
 
+                if not meta:
53
 
+                    from bzrlib.inventory import Meta
54
 
+                    inv_entry.meta = Meta({property:value})
55
 
+                else:
56
 
+                    inv_entry.meta.properties[property] = value
57
 
+                b.inventory = inv # This should cause it to be saved
58
 
+            elif unset:
59
 
+                if not meta or not meta.properties.has_key(property):
60
 
+                    return 3 # Cannot unset a property that doesn't exist
61
 
+                    # I wonder if this should be a different return code
62
 
+                del inv_entry.meta.properties[property]
63
 
+                b.inventory = inv
64
 
+            else:
65
 
+                if not meta or not meta.properties.has_key(property):
66
 
+                    return 3 # Missing property
67
 
+                # Probably this should not be print, but 
68
 
+                # sys.stdout.write() so that you get back exactly
69
 
+                # what was given. But I'm leaving it this way for now
70
 
+                print meta.properties[property]
71
 
 
72
 
 # list of all available options; the rhs can be either None for an
73
 
 # option that takes no argument, or a constructor function that checks
74
 
@@ -1196,6 +1257,8 @@
75
 
     'verbose':                None,
76
 
     'version':                None,
77
 
     'email':                  None,
78
 
+    'set':                    None,
79
 
+    'unset':                  None,
80
 
     }
81
 
 
82
 
 SHORT_OPTIONS = {
83
 
 
84
 
*** modified file 'bzrlib/diff.py'
85
 
--- bzrlib/diff.py 
86
 
+++ bzrlib/diff.py 
87
 
@@ -226,8 +226,10 @@
88
 
                       new_tree.get_file(file_id).readlines(),
89
 
                       to_file)
90
 
 
91
 
-    for old_path, new_path, file_id, kind, text_modified in delta.renamed:
92
 
+    for old_path, new_path, file_id, kind, text_modified, meta_modified in delta.renamed:
93
 
         print '*** renamed %s %r => %r' % (kind, old_path, new_path)
94
 
+        if meta_modified:
95
 
+            print '## Meta-info modified'
96
 
         if text_modified:
97
 
             diff_file(old_label + old_path,
98
 
                       old_tree.get_file(file_id).readlines(),
99
 
@@ -235,9 +237,11 @@
100
 
                       new_tree.get_file(file_id).readlines(),
101
 
                       to_file)
102
 
 
103
 
-    for path, file_id, kind in delta.modified:
104
 
+    for path, file_id, kind, text_modified, meta_modified in delta.modified:
105
 
         print '*** modified %s %r' % (kind, path)
106
 
-        if kind == 'file':
107
 
+        if meta_modified:
108
 
+            print '## Meta-info modified'
109
 
+        if kind == 'file' and text_modified:
110
 
             diff_file(old_label + path,
111
 
                       old_tree.get_file(file_id).readlines(),
112
 
                       new_label + path,
113
 
@@ -316,7 +320,7 @@
114
 
 
115
 
         if self.renamed:
116
 
             print >>to_file, 'renamed:'
117
 
-            for oldpath, newpath, fid, kind, text_modified in self.renamed:
118
 
+            for oldpath, newpath, fid, kind, text_modified, meta_modified in self.renamed:
119
 
                 if show_ids:
120
 
                     print >>to_file, '  %s => %s %s' % (oldpath, newpath, fid)
121
 
                 else:
122
 
@@ -324,7 +328,16 @@
123
 
                     
124
 
         if self.modified:
125
 
             print >>to_file, 'modified:'
126
 
-            show_list(self.modified)
127
 
+            for path, fid, kind, text_modified, meta_modified in self.modified:
128
 
+                if kind == 'directory':
129
 
+                    path += '/'
130
 
+                elif kind == 'symlink':
131
 
+                    path += '@'
132
 
+                    
133
 
+                if show_ids:
134
 
+                    print >>to_file, '  %-30s %s' % (path, fid)
135
 
+                else:
136
 
+                    print >>to_file, ' ', path
137
 
             
138
 
         if show_unchanged and self.unchanged:
139
 
             print >>to_file, 'unchanged:'
140
 
@@ -388,6 +401,14 @@
141
 
                 ## mutter("no text to check for %r %r" % (file_id, kind))
142
 
                 text_modified = False
143
 
 
144
 
+            old_meta = old_inv[file_id].meta
145
 
+            new_meta = new_inv[file_id].meta
146
 
+
147
 
+            if old_meta != new_meta:
148
 
+                meta_modified = True
149
 
+            else:
150
 
+                meta_modified = False
151
 
+
152
 
             # TODO: Can possibly avoid calculating path strings if the
153
 
             # two files are unchanged and their names and parents are
154
 
             # the same and the parents are unchanged all the way up.
155
 
@@ -395,9 +416,10 @@
156
 
             
157
 
             if old_path != new_path:
158
 
                 delta.renamed.append((old_path, new_path, file_id, kind,
159
 
-                                      text_modified))
160
 
-            elif text_modified:
161
 
-                delta.modified.append((new_path, file_id, kind))
162
 
+                                      text_modified, meta_modified))
163
 
+            elif text_modified or meta_modified:
164
 
+                delta.modified.append((new_path, file_id, kind,
165
 
+                                       text_modified, meta_modified))
166
 
             elif want_unchanged:
167
 
                 delta.unchanged.append((new_path, file_id, kind))
168
 
         else:
169
 
 
170
 
*** modified file 'bzrlib/inventory.py'
171
 
--- bzrlib/inventory.py 
172
 
+++ bzrlib/inventory.py 
173
 
@@ -33,6 +33,67 @@
174
 
 import bzrlib
175
 
 from bzrlib.osutils import uuid, quotefn, splitpath, joinpath, appendpath
176
 
 from bzrlib.trace import mutter
177
 
+
178
 
+class Meta(XMLMixin):
179
 
+    """Meta information about a single inventory entry.
180
 
+
181
 
+    This is basically just a set of key->value pairs.
182
 
+
183
 
+    In general, bzr does not handle this information, it only provides
184
 
+    a location for plugins and other data sources to store this data.
185
 
+
186
 
+    """
187
 
+    def __init__(self, properties):
188
 
+        self.properties = properties
189
 
+
190
 
+    def __eq__(self, other):
191
 
+        if other is None:
192
 
+            return False
193
 
+        if not isinstance(other, Meta):
194
 
+            return NotImplemented
195
 
+
196
 
+        return (self.properties == other.properties)
197
 
+
198
 
+    def __ne__(self, other):
199
 
+        return not (self == other)
200
 
+
201
 
+    def __hash__(self):
202
 
+        raise ValueError('not hashable')
203
 
+
204
 
+    def from_element(cls, elt):
205
 
+        assert elt.tag == 'meta'
206
 
+
207
 
+        properties = {}
208
 
+        for child in elt:
209
 
+            if child.tag == 'property':
210
 
+                if child.text is None:
211
 
+                    properties[child.get('name')] = ''
212
 
+                else:
213
 
+                    properties[child.get('name')] = child.text
214
 
+        self = cls(properties)
215
 
+        return self
216
 
+
217
 
+    from_element = classmethod(from_element)
218
 
+
219
 
+    def to_element(self):
220
 
+        e = Element('meta')
221
 
+        keys = self.properties.keys()
222
 
+        keys.sort()
223
 
+
224
 
+        # The blah.text is just to make things look pretty in the files
225
 
+        # We may want to remove it
226
 
+        if len(keys) > 0:
227
 
+            e.text = '\n'
228
 
+
229
 
+        for key in keys:
230
 
+            prop = Element('property')
231
 
+            prop.set('name', key)
232
 
+            prop.text=self.properties[key]
233
 
+            prop.tail='\n'
234
 
+            e.append(prop)
235
 
+
236
 
+        return e
237
 
+
238
 
 
239
 
 class InventoryEntry(XMLMixin):
240
 
     """Description of a versioned file.
241
 
@@ -100,6 +161,7 @@
242
 
 
243
 
     text_sha1 = None
244
 
     text_size = None
245
 
+    meta = None
246
 
     
247
 
     def __init__(self, file_id, name, kind, parent_id, text_id=None):
248
 
         """Create an InventoryEntry
249
 
@@ -124,6 +186,7 @@
250
 
         self.kind = kind
251
 
         self.text_id = text_id
252
 
         self.parent_id = parent_id
253
 
+        self.meta = None
254
 
         if kind == 'directory':
255
 
             self.children = {}
256
 
         elif kind == 'file':
257
 
@@ -146,6 +209,10 @@
258
 
         other.text_size = self.text_size
259
 
         # note that children are *not* copied; they're pulled across when
260
 
         # others are added
261
 
+        if self.meta:
262
 
+            other.meta = Meta(self.meta.properties)
263
 
+        else:
264
 
+            other.meta = None
265
 
         return other
266
 
 
267
 
 
268
 
@@ -182,6 +249,9 @@
269
 
             e.set('parent_id', self.parent_id)
270
 
 
271
 
         e.tail = '\n'
272
 
+
273
 
+        if self.meta:
274
 
+            e.append(self.meta.to_element())
275
 
             
276
 
         return e
277
 
 
278
 
@@ -205,6 +275,11 @@
279
 
         v = elt.get('text_size')
280
 
         self.text_size = v and int(v)
281
 
 
282
 
+        self.meta = None
283
 
+        for child in elt:
284
 
+            if child.tag == 'meta':
285
 
+                self.meta = Meta.from_element(child)
286
 
+
287
 
         return self
288
 
             
289
 
 
290
 
@@ -220,7 +295,8 @@
291
 
                and (self.text_size == other.text_size) \
292
 
                and (self.text_id == other.text_id) \
293
 
                and (self.parent_id == other.parent_id) \
294
 
-               and (self.kind == other.kind)
295
 
+               and (self.kind == other.kind) \
296
 
+               and (self.meta == other.meta)
297
 
 
298
 
 
299
 
     def __ne__(self, other):
300