Gentoo Archives: gentoo-portage-dev

From: Mike Frysinger <vapier@g.o>
To: gentoo-portage-dev@l.g.o
Subject: [gentoo-portage-dev] [PATCH] dispatch-conf: do regex matching ourselves
Date: Fri, 09 Mar 2012 00:10:04
Message-Id: 1331243308-23465-1-git-send-email-vapier@gentoo.org
1 This avoids having to pipe through multiple greps, as well as running
2 diff multiple times on the same set of files.
3
4 Signed-off-by: Mike Frysinger <vapier@g.o>
5 ---
6 bin/dispatch-conf | 37 ++++++++++++++++++++++++-------------
7 pym/portage/dispatch_conf.py | 8 ++++----
8 2 files changed, 28 insertions(+), 17 deletions(-)
9
10 diff --git a/bin/dispatch-conf b/bin/dispatch-conf
11 index a778118..f6d7499 100755
12 --- a/bin/dispatch-conf
13 +++ b/bin/dispatch-conf
14 @@ -27,13 +27,11 @@ except ImportError:
15 from portage import os
16 from portage import dispatch_conf
17 from portage import _unicode_decode
18 -from portage.dispatch_conf import diffstatusoutput_len
19 +from portage.dispatch_conf import diffstatusoutput
20 from portage.process import find_binary
21
22 FIND_EXTANT_CONFIGS = "find '%s' %s -name '._cfg????_%s' ! -name '.*~' ! -iname '.*.bak' -print"
23 DIFF_CONTENTS = "diff -Nu '%s' '%s'"
24 -DIFF_CVS_INTERP = "diff -Nu '%s' '%s' | grep '^[+-][^+-]' | grep -v '# .Header:.*'"
25 -DIFF_WSCOMMENTS = "diff -Nu '%s' '%s' | grep '^[+-][^+-]' | grep -v '^[-+]#' | grep -v '^[-+][[:space:]]*$'"
26
27 # We need a secure scratch dir and python does silly verbose errors on the use of tempnam
28 oldmask = os.umask(0o077)
29 @@ -62,7 +60,7 @@ def cleanup(mydir=SCRATCH_DIR):
30 shutil.rmtree(mydir)
31 atexit.register(cleanup)
32
33 -MANDATORY_OPTS = [ 'archive-dir', 'diff', 'replace-cvs', 'replace-wscomments', 'merge' ]
34 +MANDATORY_OPTS = [ 'archive-dir', 'diff', 'replace-cvs', 'replace-wscomments', 'merge' ]
35
36 def cmd_var_is_valid(cmd):
37 """
38 @@ -152,6 +150,9 @@ class dispatch:
39 portage.util.shlex_split(
40 portage.settings.get('CONFIG_PROTECT_MASK', '')))
41
42 + def diff(file1, file2):
43 + return diffstatusoutput(DIFF_CONTENTS, file1, file2)
44 +
45 #
46 # Remove new configs identical to current
47 # and
48 @@ -168,11 +169,11 @@ class dispatch:
49 else:
50 mrgfail = portage.dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf)
51 if os.path.exists(archive + '.dist'):
52 - unmodified = diffstatusoutput_len(DIFF_CONTENTS % (conf['current'], archive + '.dist'))[1] == 0
53 + unmodified = len(diff(conf['current'], archive + '.dist')[1]) == 0
54 else:
55 unmodified = 0
56 if os.path.exists(mrgconf):
57 - if mrgfail or diffstatusoutput_len(DIFF_CONTENTS % (conf['new'], mrgconf))[1] == 0:
58 + if mrgfail or len(diff(conf['new'], mrgconf)[1]) == 0:
59 os.unlink(mrgconf)
60 newconf = conf['new']
61 else:
62 @@ -183,24 +184,34 @@ class dispatch:
63 if newconf == mrgconf and \
64 self.options.get('ignore-previously-merged') != 'yes' and \
65 os.path.exists(archive+'.dist') and \
66 - diffstatusoutput_len(DIFF_CONTENTS % (archive+'.dist', conf['new']))[1] == 0:
67 + len(diff(archive+'.dist', conf['new'])[1]) == 0:
68 # The current update is identical to the archived .dist
69 # version that has previously been merged.
70 os.unlink(mrgconf)
71 newconf = conf['new']
72
73 - mystatus, myoutput_len = diffstatusoutput_len(
74 - DIFF_CONTENTS % (conf ['current'], newconf))
75 + mystatus, myoutput = diff(conf['current'], newconf)
76 + myoutput_len = len(myoutput)
77 same_file = 0 == myoutput_len
78 if mystatus >> 8 == 2:
79 # Binary files differ
80 same_cvs = False
81 same_wsc = False
82 else:
83 - same_cvs = 0 == diffstatusoutput_len(
84 - DIFF_CVS_INTERP % (conf ['current'], newconf))[1]
85 - same_wsc = 0 == diffstatusoutput_len(
86 - DIFF_WSCOMMENTS % (conf ['current'], newconf))[1]
87 + # Extract all the normal diff lines (ignore the headers).
88 + mylines = re.findall('^[+-][^\n+-].*$', myoutput, re.MULTILINE)
89 +
90 + # Filter out all the cvs headers
91 + cvs_header = re.compile('# [$]Header:')
92 + cvs_lines = filter(cvs_header.search, mylines)
93 + same_cvs = len(mylines) == len(cvs_lines)
94 +
95 + # Filter out comments and whitespace-only changes.
96 + # Note: be nice to also ignore lines that only differ in whitespace...
97 + wsc_lines = []
98 + for x in ['^[-+]\s*#', '^[-+]\s*$']:
99 + wsc_lines += filter(re.compile(x).match, mylines)
100 + same_wsc = len(mylines) == len(wsc_lines)
101
102 # Do options permit?
103 same_cvs = same_cvs and self.options['replace-cvs'] == 'yes'
104 diff --git a/pym/portage/dispatch_conf.py b/pym/portage/dispatch_conf.py
105 index 7f407ff..6e8de0f 100644
106 --- a/pym/portage/dispatch_conf.py
107 +++ b/pym/portage/dispatch_conf.py
108 @@ -23,18 +23,18 @@ RCS_MERGE = "rcsmerge -p -r" + RCS_BRANCH + " '%s' > '%s'"
109
110 DIFF3_MERGE = "diff3 -mE '%s' '%s' '%s' > '%s'"
111
112 -def diffstatusoutput_len(cmd):
113 +def diffstatusoutput(cmd, file1, file2):
114 """
115 Execute the string cmd in a shell with getstatusoutput() and return a
116 - 2-tuple (status, output_length). If getstatusoutput() raises
117 + 2-tuple (status, output). If getstatusoutput() raises
118 UnicodeDecodeError (known to happen with python3.1), return a
119 2-tuple (1, 1). This provides a simple way to check for non-zero
120 output length of diff commands, while providing simple handling of
121 UnicodeDecodeError when necessary.
122 """
123 try:
124 - status, output = portage.subprocess_getstatusoutput(cmd)
125 - return (status, len(output))
126 + status, output = portage.subprocess_getstatusoutput(cmd % (file1, file2))
127 + return (status, output)
128 except UnicodeDecodeError:
129 return (1, 1)
130
131 --
132 1.7.8.4

Replies