2 from stgit
import exception
, utils
3 from stgit
.lib
import git
, stackupgrade
6 def __init__(self
, stack
, name
):
9 name
= property(lambda self
: self
.__name
)
12 return 'refs/patches/%s/%s' %
(self
.__stack
.name
, self
.__name
)
15 return self
.__ref
+ '.log'
18 return self
.__stack
.repository
.refs
.get(self
.__ref
)
20 def __compat_dir(self
):
21 return os
.path
.join(self
.__stack
.directory
, 'patches', self
.__name
)
22 def __write_compat_files(self
, new_commit
, msg
):
23 """Write files used by the old infrastructure."""
24 def write(name
, val
, multiline
= False):
25 fn
= os
.path
.join(self
.__compat_dir
, name
)
27 utils
.write_string(fn
, val
, multiline
)
28 elif os
.path
.isfile(fn
):
32 old_log
= [self
.__stack
.repository
.refs
.get(self
.__log_ref
)]
35 cd
= git
.CommitData(tree
= new_commit
.data
.tree
, parents
= old_log
,
36 message
= '%s\t%s' %
(msg
, new_commit
.sha1
))
37 c
= self
.__stack
.repository
.commit(cd
)
38 self
.__stack
.repository
.refs
.set(self
.__log_ref
, c
, msg
)
41 write('authname', d
.author
.name
)
42 write('authemail', d
.author
.email
)
43 write('authdate', d
.author
.date
)
44 write('commname', d
.committer
.name
)
45 write('commemail', d
.committer
.email
)
46 write('description', d
.message
)
47 write('log', write_patchlog().sha1
)
48 write('top', new_commit
.sha1
)
49 write('bottom', d
.parent
.sha1
)
51 old_top_sha1
= self
.commit
.sha1
52 old_bottom_sha1
= self
.commit
.data
.parent
.sha1
55 old_bottom_sha1
= None
56 write('top.old', old_top_sha1
)
57 write('bottom.old', old_bottom_sha1
)
58 def __delete_compat_files(self
):
59 if os
.path
.isdir(self
.__compat_dir
):
60 for f
in os
.listdir(self
.__compat_dir
):
61 os
.remove(os
.path
.join(self
.__compat_dir
, f
))
62 os
.rmdir(self
.__compat_dir
)
63 self
.__stack
.repository
.refs
.delete(self
.__log_ref
)
64 def set_commit(self
, commit
, msg
):
65 self
.__write_compat_files(commit
, msg
)
66 self
.__stack
.repository
.refs
.set(self
.__ref
, commit
, msg
)
68 self
.__delete_compat_files()
69 self
.__stack
.repository
.refs
.delete(self
.__ref
)
71 return self
.name
in self
.__stack
.patchorder
.applied
73 return self
.commit
.data
.is_nochange()
75 class PatchOrder(object):
76 """Keeps track of patch order, and which patches are applied.
77 Works with patch names, not actual patches."""
78 def __init__(self
, stack
):
81 def __read_file(self
, fn
):
82 return tuple(utils
.read_strings(
83 os
.path
.join(self
.__stack
.directory
, fn
)))
84 def __write_file(self
, fn
, val
):
85 utils
.write_strings(os
.path
.join(self
.__stack
.directory
, fn
), val
)
86 def __get_list(self
, name
):
87 if not name
in self
.__lists
:
88 self
.__lists
[name
] = self
.__read_file(name
)
89 return self
.__lists
[name
]
90 def __set_list(self
, name
, val
):
92 if val
!= self
.__lists
.get(name
, None):
93 self
.__lists
[name
] = val
94 self
.__write_file(name
, val
)
95 applied
= property(lambda self
: self
.__get_list('applied'),
96 lambda self
, val
: self
.__set_list('applied', val
))
97 unapplied
= property(lambda self
: self
.__get_list('unapplied'),
98 lambda self
, val
: self
.__set_list('unapplied', val
))
99 hidden
= property(lambda self
: self
.__get_list('hidden'),
100 lambda self
, val
: self
.__set_list('hidden', val
))
101 # don't return the hidden patches, these have to be returned explicitly
102 all
= property(lambda self
: self
.applied
+ self
.unapplied
)
104 class Patches(object):
105 """Creates Patch objects."""
106 def __init__(self
, stack
):
108 def create_patch(name
):
109 p
= Patch(self
.__stack
, name
)
110 p
.commit
# raise exception if the patch doesn't exist
112 self
.__patches
= git
.ObjectCache(create_patch
) # name -> Patch
113 def exists(self
, name
):
120 return self
.__patches
[name
]
121 def new(self
, name
, commit
, msg
):
122 assert not name
in self
.__patches
123 p
= Patch(self
.__stack
, name
)
124 p
.set_commit(commit
, msg
)
125 self
.__patches
[name
] = p
129 def __init__(self
, repository
, name
):
130 self
.__repository
= repository
135 raise exception
.StgException('%s: no such branch' % name
)
136 self
.__patchorder
= PatchOrder(self
)
137 self
.__patches
= Patches(self
)
138 if not stackupgrade
.update_to_current_format_version(repository
, name
):
139 raise exception
.StgException('%s: branch not initialized' % name
)
140 name
= property(lambda self
: self
.__name
)
141 repository
= property(lambda self
: self
.__repository
)
142 patchorder
= property(lambda self
: self
.__patchorder
)
143 patches
= property(lambda self
: self
.__patches
)
146 return os
.path
.join(self
.__repository
.directory
, 'patches', self
.__name
)
148 return 'refs/heads/%s' % self
.__name
151 return self
.__repository
.refs
.get(self
.__ref())
152 def set_head(self
, commit
, msg
):
153 self
.__repository
.refs
.set(self
.__ref(), commit
, msg
)
156 if self
.patchorder
.applied
:
157 return self
.patches
.get(self
.patchorder
.applied
[0]
161 def head_top_equal(self
):
162 if not self
.patchorder
.applied
:
164 return self
.head
== self
.patches
.get(self
.patchorder
.applied
[-1]).commit
166 class Repository(git
.Repository
):
167 def __init__(self
, *args
, **kwargs
):
168 git
.Repository
.__init__(self
, *args
, **kwargs
)
169 self
.__stacks
= {} # name -> Stack
171 def current_branch(self
):
172 return utils
.strip_leading('refs/heads/', self
.head
)
174 def current_stack(self
):
175 return self
.get_stack(self
.current_branch
)
176 def get_stack(self
, name
):
177 if not name
in self
.__stacks
:
178 self
.__stacks
[name
] = Stack(self
, name
)
179 return self
.__stacks
[name
]