/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: Robert Collins
  • Date: 2005-10-16 00:22:17 UTC
  • mto: This revision was merged to the branch mainline in revision 1457.
  • Revision ID: robertc@lifelesslap.robertcollins.net-20051016002217-aa38f9c1eb13ee48
Plugins are now loaded under bzrlib.plugins, not bzrlib.plugin.

Plugins are also made available for other plugins to use by making them 
accessible via import bzrlib.plugins.NAME. You should not import other
plugins during the __init__ of your plugin though, as no ordering is
guaranteed, and the plugins directory is not on the python path.

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