|
1 # repoview.py - Filtered view of a localrepo object |
|
2 # |
|
3 # Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org> |
|
4 # Logilab SA <contact@logilab.fr> |
|
5 # |
|
6 # This software may be used and distributed according to the terms of the |
|
7 # GNU General Public License version 2 or any later version. |
|
8 |
|
9 import copy |
|
10 |
|
11 # function to compute filtered set |
|
12 filtertable = {} |
|
13 |
|
14 def filteredrevs(repo, filtername): |
|
15 """returns set of filtered revision for this filter name""" |
|
16 return filtertable[filtername](repo.unfiltered()) |
|
17 |
|
18 class repoview(object): |
|
19 """Provide a read/write view of a repo through a filtered changelog |
|
20 |
|
21 This object is used to access a filtered version of a repository without |
|
22 altering the original repository object itself. We can not alter the |
|
23 original object for two main reasons: |
|
24 - It prevents the use of a repo with multiple filters at the same time. In |
|
25 particular when multiple threads are involved. |
|
26 - It makes scope of the filtering harder to control. |
|
27 |
|
28 This object behaves very closely to the original repository. All attribute |
|
29 operations are done on the original repository: |
|
30 - An access to `repoview.someattr` actually returns `repo.someattr`, |
|
31 - A write to `repoview.someattr` actually sets value of `repo.someattr`, |
|
32 - A deletion of `repoview.someattr` actually drops `someattr` |
|
33 from `repo.__dict__`. |
|
34 |
|
35 The only exception is the `changelog` property. It is overridden to return |
|
36 a (surface) copy of `repo.changelog` with some revisions filtered. The |
|
37 `filtername` attribute of the view control the revisions that need to be |
|
38 filtered. (the fact the changelog is copied is an implementation detail). |
|
39 |
|
40 Unlike attributes, this object intercepts all method calls. This means that |
|
41 all methods are run on the `repoview` object with the filtered `changelog` |
|
42 property. For this purpose the simple `repoview` class must be mixed with |
|
43 the actual class of the repository. This ensures that the resulting |
|
44 `repoview` object have the very same methods than the repo object. This |
|
45 leads to the property below. |
|
46 |
|
47 repoview.method() --> repo.__class__.method(repoview) |
|
48 |
|
49 The inheritance has to be done dynamically because `repo` can be of any |
|
50 subclasses of `localrepo`. Eg: `bundlerepo` or `httprepo`. |
|
51 """ |
|
52 |
|
53 def __init__(self, repo, filtername): |
|
54 object.__setattr__(self, '_unfilteredrepo', repo) |
|
55 object.__setattr__(self, 'filtername', filtername) |
|
56 |
|
57 # not a cacheproperty on purpose we shall implement a proper cache later |
|
58 @property |
|
59 def changelog(self): |
|
60 """return a filtered version of the changeset |
|
61 |
|
62 this changelog must not be used for writing""" |
|
63 # some cache may be implemented later |
|
64 cl = copy.copy(self._unfilteredrepo.changelog) |
|
65 cl.filteredrevs = filteredrevs(self._unfilteredrepo, self.filtername) |
|
66 return cl |
|
67 |
|
68 def unfiltered(self): |
|
69 """Return an unfiltered version of a repo""" |
|
70 return self._unfilteredrepo |
|
71 |
|
72 def filtered(self, name): |
|
73 """Return a filtered version of a repository""" |
|
74 if name == self.filtername: |
|
75 return self |
|
76 return self.unfiltered().filtered(name) |
|
77 |
|
78 # everything access are forwarded to the proxied repo |
|
79 def __getattr__(self, attr): |
|
80 return getattr(self._unfilteredrepo, attr) |
|
81 |
|
82 def __setattr__(self, attr, value): |
|
83 return setattr(self._unfilteredrepo, attr, value) |
|
84 |
|
85 def __delattr__(self, attr): |
|
86 return delattr(self._unfilteredrepo, attr) |
|
87 |
|
88 # The `requirement` attribut is initialiazed during __init__. But |
|
89 # __getattr__ won't be called as it also exists on the class. We need |
|
90 # explicit forwarding to main repo here |
|
91 @property |
|
92 def requirements(self): |
|
93 return self._unfilteredrepo.requirements |
|
94 |