Lines 20-25
Link Here
|
20 |
DIFF_WSCOMMENTS = 'diff -Nau %s %s | grep "^[+-][^+-]" | grep -v "^[-+]#" | grep -v "^[-+][:space:]*$"' |
20 |
DIFF_WSCOMMENTS = 'diff -Nau %s %s | grep "^[+-][^+-]" | grep -v "^[-+]#" | grep -v "^[-+][:space:]*$"' |
21 |
MERGE = 'sdiff --suppress-common-lines --output=%s %s %s' |
21 |
MERGE = 'sdiff --suppress-common-lines --output=%s %s %s' |
22 |
|
22 |
|
|
|
23 |
RCS_BRANCH = '1.1.1' |
24 |
RCS_LOCK = 'rcs -ko -M -l' |
25 |
RCS_PUT = 'ci -t-"Archived config file." -m"dispatch-conf update."' |
26 |
RCS_GET = 'co' |
27 |
RCS_MERGE = 'rcsmerge -p -r' + RCS_BRANCH + ' %s >%s' |
28 |
|
23 |
MANDATORY_OPTS = [ 'archive-dir', 'diff', 'pager', 'replace-cvs', 'replace-wscomments' ] |
29 |
MANDATORY_OPTS = [ 'archive-dir', 'diff', 'pager', 'replace-cvs', 'replace-wscomments' ] |
24 |
|
30 |
|
25 |
class dispatch: |
31 |
class dispatch: |
Lines 50-68
Link Here
|
50 |
# |
56 |
# |
51 |
|
57 |
|
52 |
def f (conf): |
58 |
def f (conf): |
53 |
same_file = len(commands.getoutput (DIFF_CONTENTS % (conf ['current'], conf ['new']))) == 0 |
59 |
mrgconf = re.sub (r'\._cfg', '._mrg', conf ['new']) |
54 |
same_cvs = len(commands.getoutput (DIFF_CVS_INTERP % (conf ['current'], conf ['new']))) == 0 |
60 |
if os.path.exists (mrgconf): |
55 |
same_wsc = len(commands.getoutput (DIFF_WSCOMMENTS % (conf ['current'], conf ['new']))) == 0 |
61 |
newconf = mrgconf |
|
|
62 |
unmodified = 0 |
63 |
else: |
64 |
newconf = self.do_rcs (conf ['new'], conf ['current'], mrgconf) |
65 |
if newconf == mrgconf: |
66 |
unmodified = len(commands.getoutput (DIFF_CONTENTS % (conf ['new'], mrgconf))) == 0 |
67 |
else: |
68 |
unmodified = 0 |
69 |
|
70 |
same_file = len(commands.getoutput (DIFF_CONTENTS % (conf ['current'], newconf))) == 0 |
71 |
same_cvs = len(commands.getoutput (DIFF_CVS_INTERP % (conf ['current'], newconf))) == 0 |
72 |
same_wsc = len(commands.getoutput (DIFF_WSCOMMENTS % (conf ['current'], newconf))) == 0 |
56 |
|
73 |
|
57 |
# Do options permit? |
74 |
# Do options permit? |
58 |
same_cvs = same_cvs and self.options ['replace-cvs'] == 'yes' |
75 |
same_cvs = same_cvs and self.options ['replace-cvs'] == 'yes' |
59 |
same_wsc = same_wsc and self.options ['replace-wscomments'] == 'yes' |
76 |
same_wsc = same_wsc and self.options ['replace-wscomments'] == 'yes' |
|
|
77 |
unmodified = unmodified and self.options ['replace-unmodified'] == 'yes' |
60 |
|
78 |
|
61 |
if same_file: |
79 |
if same_file or unmodified: |
62 |
os.unlink (conf ['new']) |
80 |
os.unlink (conf ['new']) |
|
|
81 |
if os.path.exists (mrgconf): |
82 |
os.unlink (mrgconf) |
63 |
return False |
83 |
return False |
64 |
elif same_cvs or same_wsc or conf ['dir'] in portage.settings ['CONFIG_PROTECT_MASK'].split (): |
84 |
elif same_cvs or same_wsc or conf ['dir'] in portage.settings ['CONFIG_PROTECT_MASK'].split (): |
65 |
self.replace (conf ['new'], conf ['current']) |
85 |
self.replace (newconf, conf ['current']) |
|
|
86 |
if newconf == mrgconf: |
87 |
os.unlink (conf ['new']) |
88 |
elif os.path.exists (mrgconf): |
89 |
os.unlink (mrgconf) |
66 |
return False |
90 |
return False |
67 |
else: |
91 |
else: |
68 |
return True |
92 |
return True |
Lines 76-144
Link Here
|
76 |
for conf in confs: |
100 |
for conf in confs: |
77 |
count = count + 1 |
101 |
count = count + 1 |
78 |
|
102 |
|
|
|
103 |
newconf = conf ['new'] |
104 |
mrgconf = re.sub (r'\._cfg', '._mrg', newconf) |
105 |
if os.path.exists (mrgconf): |
106 |
newconf = mrgconf |
107 |
show_new_diff = 0 |
108 |
|
79 |
while 1: |
109 |
while 1: |
80 |
os.system ((self.options ['diff'] + '| %s') % (conf ['current'], conf ['new'], self.options ['pager'])) |
110 |
if show_new_diff: |
|
|
111 |
os.system ((self.options ['diff'] + '| %s') % (conf ['new'], mrgconf, self.options ['pager'])) |
112 |
show_new_diff = 0 |
113 |
else: |
114 |
os.system ((self.options ['diff'] + '| %s') % (conf ['current'], newconf, self.options ['pager'])) |
81 |
|
115 |
|
82 |
print |
116 |
print |
83 |
print '>> (%i of %i) -- %s' % (count, len(confs), conf ['current']) |
117 |
print '>> (%i of %i) -- %s' % (count, len(confs), conf ['current']) |
84 |
print '>> q quit, h help, n skip, f fuse/merge, k kill new, s supercede w/new', |
118 |
print '>> q quit, h help, n next, e edit-new, z zap-new, u use-new\n m merge, t toggle-merge, l look-merge: ', |
85 |
|
119 |
|
86 |
c = getch () |
120 |
c = getch () |
87 |
|
121 |
|
88 |
if c == 'q': |
122 |
if c == 'q': |
89 |
sys.exit (0) |
123 |
sys.exit (0) |
90 |
if c == 'h': |
124 |
if c == 'h': |
91 |
do_help () |
125 |
self.do_help () |
|
|
126 |
continue |
127 |
elif c == 't': |
128 |
if newconf == mrgconf: |
129 |
newconf = conf ['new'] |
130 |
elif os.path.exists (mrgconf): |
131 |
newconf = mrgconf |
92 |
continue |
132 |
continue |
93 |
elif c == 'n': |
133 |
elif c == 'n': |
94 |
break |
134 |
break |
95 |
elif c == 'f': |
135 |
elif c == 'm': |
96 |
merged = '/tmp/dispatch-conf.merged.%i' % (os.getpid (),) |
136 |
merged = '/tmp/dispatch-conf.merged.%i' % (os.getpid (),) |
97 |
print |
137 |
print |
98 |
os.system (MERGE % (merged, conf ['current'], conf ['new'])) |
138 |
os.system (MERGE % (merged, conf ['current'], newconf)) |
99 |
os.rename (merged, conf ['new']) |
139 |
os.rename (merged, mrgconf) |
|
|
140 |
newconf = mrgconf |
141 |
continue |
142 |
elif c == 'l': |
143 |
show_new_diff = 1 |
144 |
continue |
145 |
elif c == 'e': |
146 |
os.system ('vim %s' % (newconf)) |
100 |
continue |
147 |
continue |
101 |
elif c == 'k': |
148 |
elif c == 'z': |
102 |
os.remove (conf ['new']) |
149 |
os.unlink (conf ['new']) |
|
|
150 |
if os.path.exists (mrgconf): |
151 |
os.unlink (mrgconf) |
103 |
break |
152 |
break |
104 |
elif c == 's': |
153 |
elif c == 'u': |
105 |
self.replace (conf ['new'], conf ['current']) |
154 |
self.replace (newconf, conf ['current']) |
|
|
155 |
if newconf == mrgconf: |
156 |
os.unlink (conf ['new']) |
157 |
elif os.path.exists (mrgconf): |
158 |
os.unlink (mrgconf) |
106 |
break |
159 |
break |
107 |
else: |
160 |
else: |
108 |
continue |
161 |
continue |
109 |
|
162 |
|
110 |
|
163 |
|
111 |
def replace (self, newconf, curconf): |
164 |
def do_rcs (self, newconf, curconf, mrgconf): |
112 |
"""Archive existing config, then replace current with new""" |
165 |
"""Archive existing config in rcs (on trunk). Then, if an old branch |
113 |
full = os.path.join (self.options ['archive-dir'], curconf.lstrip ('/')) |
166 |
version exists, merge the user's changes and the distributed changes |
114 |
|
167 |
and put the result into mrgconf. Next, archive the new distributed |
|
|
168 |
version on the 1.1.1 branch of the rcs file. We return the mrgconf |
169 |
name if a merge happened, else newconf.""" |
170 |
archive = os.path.join (self.options ['archive-dir'], curconf.lstrip ('/')) |
115 |
try: |
171 |
try: |
116 |
os.makedirs (os.path.dirname (full)) |
172 |
os.makedirs (os.path.dirname (archive)) |
117 |
except: |
173 |
except: |
118 |
pass |
174 |
pass |
119 |
|
175 |
|
120 |
count = 1 |
176 |
try: |
121 |
while count < 1000: |
177 |
shutil.copy2 (curconf, archive) |
122 |
archive = full + '.' + str(count) |
178 |
except (IOError, os.error), why: |
|
|
179 |
print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \ |
180 |
(curconf, archive, str(why)) |
181 |
if (os.path.exists (archive + ',v')): |
182 |
os.system (RCS_LOCK + ' ' + archive) |
183 |
os.system (RCS_PUT + ' ' + archive) |
184 |
|
185 |
# There is probably a better way of checking for the branch... |
186 |
os.system (RCS_GET + ' -r' + RCS_BRANCH + ' ' + archive) |
187 |
has_branch = os.path.exists (archive) |
123 |
|
188 |
|
124 |
if os.path.exists (archive): |
189 |
try: |
125 |
count = count + 1 |
190 |
shutil.copy2 (newconf, archive) |
126 |
continue |
191 |
except (IOError, os.error), why: |
127 |
else: |
192 |
print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \ |
128 |
try: |
193 |
(newconf, archive, str(why)) |
129 |
shutil.copy2 (curconf, archive) |
194 |
if has_branch: |
130 |
except (IOError, os.error), why: |
195 |
# This puts the results of the merge into mrgconf. |
131 |
print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \ |
196 |
os.system (RCS_MERGE % (archive, mrgconf)) |
132 |
(curconf, archive, str(why)) |
197 |
# Commit the last-distributed version onto the branch. |
133 |
try: |
198 |
os.system (RCS_LOCK + RCS_BRANCH + ' ' + archive) |
134 |
os.rename (newconf, curconf) |
199 |
os.system (RCS_PUT + ' -r' + RCS_BRANCH + ' ' + archive) |
135 |
except (IOError, os.error), why: |
200 |
return mrgconf |
136 |
print >> sys.stderr, 'dispatch-conf: Error renaming %s to %s: %s; fatal' % \ |
201 |
|
137 |
(newconf, curconf, str(why)) |
202 |
# Forcefully commit the last-distributed version onto the branch. |
138 |
break |
203 |
os.system (RCS_PUT + ' -f -r' + RCS_BRANCH + ' ' + archive) |
139 |
else: |
204 |
return newconf |
140 |
print >> sys.stderr, 'dispatch-conf: Error archiving files -- exhausted slots???; fatal' |
205 |
|
141 |
sys.exit (1) |
206 |
|
|
|
207 |
def replace (self, newconf, curconf): |
208 |
"""Replace current config with the new/merged version""" |
209 |
try: |
210 |
os.rename (newconf, curconf) |
211 |
except (IOError, os.error), why: |
212 |
print >> sys.stderr, 'dispatch-conf: Error renaming %s to %s: %s; fatal' % \ |
213 |
(newconf, curconf, str(why)) |
142 |
|
214 |
|
143 |
|
215 |
|
144 |
def massage (self, newconfigs): |
216 |
def massage (self, newconfigs): |
Lines 172-183
Link Here
|
172 |
def do_help (self): |
244 |
def do_help (self): |
173 |
print; print |
245 |
print; print |
174 |
|
246 |
|
175 |
print ' q -- quit' |
247 |
print ' u -- update current config with new config and continue' |
|
|
248 |
print ' z -- zap (delete) new config and continue' |
249 |
print ' n -- skip to next config, leave all intact' |
250 |
print ' e -- edit new config' |
251 |
print ' m -- interactively merge current and new configs' |
252 |
print ' l -- look at diff between pre-merged and merged configs' |
253 |
print ' t -- toggle new config between merged and pre-merged state' |
176 |
print ' h -- this screen' |
254 |
print ' h -- this screen' |
177 |
print ' n -- next/skip to next config, leave all intact' |
255 |
print ' q -- quit' |
178 |
print ' f -- interactively fuse/merge current and new configs' |
|
|
179 |
print ' k -- kill/remove new config and continue' |
180 |
print ' s -- supercede current config with new and continue' |
181 |
|
256 |
|
182 |
print; print 'press any key to return to diff...', |
257 |
print; print 'press any key to return to diff...', |
183 |
|
258 |
|