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