From e63823dd8358f50559fa616313cdde3ceaf104ed Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Tue, 28 Jun 2011 02:06:36 -0700 Subject: varexpand: handle backslashes like more like bash For backslash expansion, this function used to behave like echo -e, but that's not needed for our purposes. We want to behave like bash does when expanding a variable assignment in a sourced file, in which case it performs backslash removal for \\ and \$ but nothing more. This will fix bash compatibility for the case reported in bug #365033. --- pym/portage/tests/util/test_varExpand.py | 33 ++++++++++++++++++++++++++- pym/portage/util/__init__.py | 39 +++++++++++--------------------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/pym/portage/tests/util/test_varExpand.py b/pym/portage/tests/util/test_varExpand.py index 30aa390bf..9dd488ea3 100644 --- a/pym/portage/tests/util/test_varExpand.py +++ b/pym/portage/tests/util/test_varExpand.py @@ -1,5 +1,5 @@ # test_varExpand.py -- Portage Unit Testing Functionality -# Copyright 2006 Gentoo Foundation +# Copyright 2006-2010 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from portage.tests import TestCase @@ -21,6 +21,37 @@ class VarExpandTestCase(TestCase): msg="Got %s != %s, from varexpand( %s, %s )" % \ ( result, varDict[key], "${%s}" % key, varDict ) ) + def testVarExpandBackslashes(self): + """ + We want to behave like bash does when expanding a variable + assignment in a sourced file, in which case it performs + backslash removal for \\ and \$ but nothing more. Note that + we don't handle escaped quotes here, since genconfig() uses + shlex to handle that earlier. + """ + + varDict = {} + tests = [ + ("\\", "\\"), + ("\\\\", "\\"), + ("\\\\\\", "\\\\"), + ("\\\\\\\\", "\\\\"), + ("\\$", "$"), + ("\\\\$", "\\$"), + ("\\a", "\\a"), + ("\\b", "\\b"), + ("\\n", "\\n"), + ("\\r", "\\r"), + ("\\t", "\\t"), + ("\\\"", "\\\""), + ("\\'", "\\'"), + ] + for test in tests: + result = varexpand( test[0], varDict ) + self.assertFalse( result != test[1], + msg="Got %s != %s from varexpand( %s, %s )" \ + % ( result, test[1], test[0], varDict ) ) + def testVarExpandDoubleQuotes(self): varDict = { "a":"5" } diff --git a/pym/portage/util/__init__.py b/pym/portage/util/__init__.py index 8c5352239..ece0806e2 100644 --- a/pym/portage/util/__init__.py +++ b/pym/portage/util/__init__.py @@ -683,37 +683,24 @@ def varexpand(mystring, mydict=None): newstring=newstring+" " pos=pos+1 elif (mystring[pos]=="\\"): - #backslash expansion time + # For backslash expansion, this function used to behave like + # echo -e, but that's not needed for our purposes. We want to + # behave like bash does when expanding a variable assignment + # in a sourced file, in which case it performs backslash + # removal for \\ and \$ but nothing more. Note that we don't + # handle escaped quotes here, since genconfig() uses shlex + # to handle that earlier. if (pos+1>=len(mystring)): newstring=newstring+mystring[pos] break else: - a=mystring[pos+1] - pos=pos+2 - if a=='a': - newstring=newstring+chr(0o07) - elif a=='b': - newstring=newstring+chr(0o10) - elif a=='e': - newstring=newstring+chr(0o33) - elif (a=='f') or (a=='n'): - newstring=newstring+chr(0o12) - elif a=='r': - newstring=newstring+chr(0o15) - elif a=='t': - newstring=newstring+chr(0o11) - elif a=='v': - newstring=newstring+chr(0o13) - elif a in ('\'', '"'): - # Quote removal is handled by shlex. + a = mystring[pos + 1] + pos = pos + 2 + if a in ("\\", "$"): + newstring = newstring + a + else: newstring = newstring + mystring[pos-2:pos] - continue - elif a!='\n': - # Remove backslash only, as bash does. This takes care - # of \\. Note that we don't handle quotes here since - # quote removal is handled by shlex. - newstring=newstring+mystring[pos-1:pos] - continue + continue elif (mystring[pos]=="$") and (mystring[pos-1]!="\\"): pos=pos+1 if mystring[pos]=="{": -- cgit v1.2.3-1-g7c22