Anonymous avatar Anonymous committed ef44581

Improvements of tag command

Comments (0)

Files changed (1)

paste/deploy/tag.py

 from setuptools import Command
-from distutils.errors import DistutilsOptionError
+from setuptools.command import setopt
+from ConfigParser import NoSectionError
+from distutils.errors import *
+from distutils import log
 from pkg_resources import *
 import subprocess
 import re
                 "You must specify a version")
         if self.message is None:
             self.message = "Tagging %s version" % self.version
-
+        if self.build is None:
+            self.build = tempfile.mkdtemp(prefix='tag_checkout_')
+        if os.path.exists(self.build):
+            raise DistutilsOptionError(
+                "The build directory %s already exists" % self.build)
+            
     _svn_url_re = re.compile(r'\bURL: (.*)')
     _setup_version_re = re.compile(r'(version\s+=\s+)([^ \n\r,)]*)')
     _egg_info_re = re.compile(r'^[egg_info]$')
         metadata = PathMetadata(
             path_item, normalize_path(ei_cmd.egg_info)
         )
-        proc = subprocess.Popen(
-            ['svn', 'info', path_item],
-            stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE)
-        stdout, stderr = proc.communicate()
-        if stderr:
-            print 'Error from svn:'
-            print stderr
+        stdout = run_command(['svn', 'info', path_item])
         match = self._svn_url_re.search(stdout)
         if not match:
-            print 'svn output did not contain "URL: ...":'
-            print stdout
-            assert 0
+            raise DistutilsExecError(
+                'svn output did not contain "URL: ...":\n' + stdout)
         svn_url = match.group(1)
         if not svn_url.endswith('/trunk'):
-            print 'svn URL must end with "/trunk" (current: %r)' % svn_url
-            assert 0
+            raise DistutilsExecError(
+                'svn URL must end with "/trunk" (current: %r)' % svn_url)
         package_url = svn_url.rsplit('/', 1)[0]
         tag_url = package_url + '/tags/' + self.version
-        # @@: Should check svn status
-        command = ['svn', 'cp', '--message', self.message,
-                   svn_url, tag_url]
-        print ' '.join(command)
-        proc = subprocess.Popen(command)
-        proc.communicate()
-        tmpdir = tempfile.mkdtemp(prefix='tag_checkout_')
-        command = ['svn', 'co', '--quiet', tag_url, tmpdir]
-        print ' '.join(command)
-        subprocess.Popen(command).communicate()
-        self.update_setup_py(tmpdir)
-        self.update_setup_cfg(tmpdir)
-        print ' '.join(command)
-        subprocess.Popen(command).communicate()
-        command = ['svn', 'commit', '--message',
-                   'Auto-update of version strings', tmpdir]
-        print ' '.join(command)
-        subprocess.Popen(command).communicate()
-        print 'Removing %s' % tmpdir
-        shutil.rmtree(tmpdir)
+        run_command(['svn', 'cp', '--message', self.message,
+                     svn_url, tag_url])
+        run_command(['svn', 'co', '--quiet', tag_url, self.build])
+        self.update_setup_py()
+        self.update_setup_cfg()
+        run_command(['svn', 'commit', '--message',
+                     'Auto-update of version strings', self.build])
 
-    def update_setup_py(self, tmpdir):
-        setup_py = os.path.join(tmpdir, 'setup.py')
+    def update_setup_py(self):
+        setup_py = os.path.join(self.build, 'setup.py')
         if not os.path.exists(setup_py):
-            print 'setup.py file cannot be found at %s' % setup_py
+            log.warn('setup.py file cannot be found at %s' % setup_py)
             return
         f = open(setup_py)
         content = f.read()
         f.close()
         match = self._setup_version_re.search(content)
         if not match:
-            print 'Cannot find version info in %s' % setup_py
+            log.warn('Cannot find version info in %s' % setup_py)
         else:
             new_content = (
                 content[:match.start()]
                 + repr(self.version)
                 + content[match.end():])
             if new_content == content:
-                print 'Version string up-to-date (edit trunk yourself)'
+                log.info('Version string up-to-date (edit trunk yourself)')
             else:
                 f = open(setup_py, 'w')
                 f.write(new_content)
                 f.close()
-                print '%s version updated' % setup_py
+                log.info('%s version updated' % setup_py)
         command = [sys.executable, setup_py, 'egg_info']
 
-    def update_setup_cfg(self, tmpdir):
-        setup_cfg = os.path.join(tmpdir, 'setup.cfg')
+    def update_setup_cfg(self):
+        setup_cfg = os.path.join(self.build, 'setup.cfg')
         if not os.path.exists(setup_cfg):
-            print 'setup.cfg file cannot be found at %s' % setup_cfg
+            log.warn('setup.cfg file cannot be found at %s' % setup_cfg)
             return
+        try:
+            setopt.edit_config(
+                setup_cfg,
+                {'egg_info': {'tag_build': None,
+                              'tag_svn_revision': None}})
+        except NoSectionError:
+            # No [egg_info]; that's okay
+            pass
         f = open(setup_cfg)
-        content = f.readlines()
+        content = f.read()
         f.close()
-        new_content = []
-        egg_info_content = []
-        while content:
-            line = content.pop(0)
-            if line.strip() != '[egg_info]':
-                new_content.append(line)
-            else:
-                egg_info_content.append(line)
-                inner_line = None
-                while content:
-                    inner_line = content.pop(0)
-                    if inner_line.strip().startswith('['):
-                        break
-                    if inner_line.strip().startswith('tag_build'):
-                        continue
-                    elif inner_line.strip().startswith('tag_svn_revision'):
-                        continue
-                    if line.strip():
-                        egg_info_content.append(line)
-                if len(egg_info_content) == 1:
-                    egg_info_content = []
-                else:
-                    egg_info_content.append('\n')
-                new_content.extend(egg_info_content)
-                if inner_line:
-                    new_content.append(inner_line)
-        content = ''.join(content)
-        if not content:
-            command = ['svn', 'rm', setup_cfg]
-            print ' '.join(command)
-            subprocess.Popen(command).communicate()
-            return
-        if content != new_content:
-            f = open(setup_cfg, 'w')
-            f.write(new_content)
-            f.close()
-            print '%s updated' % setup_cfg
-        
+        if not content.strip():
+            log.info('%s empty; deleting' % setup_cfg)
+            run_command(['svn', 'rm', '--force', setup_cfg])
                     
-                    
-        
+def run_command(command_list, stdin=None):
+    log.info('Running %s', format_command(command_list))
+    proc = subprocess.Popen(command_list,
+                            stdout=subprocess.PIPE,
+                            stderr=subprocess.PIPE)
+    stdout, stderr = proc.communicate(stdin)
+    if stderr:
+        log.warn('Ouput from %s:\n%s',
+                 format_command(command_list),
+                 stderr)
+    returncode = proc.returncode
+    if returncode:
+        error = 'Exit code %s from %s' % (
+            returncode, format_command(command_list))
+        if stderr:
+            error += '; stderr output:\n' + stderr
+        raise Distutils.ExecError(error)
+    return stdout
+
+def format_command(lst):
+    return ' '.join(map(quote_command_item, lst))
+
+def quote_command_item(item):
+    if ' ' in item: # @@: Obvious I should check more characters
+        for char in ('\\', '"', "'", '$'):
+            item = item.replace(char, '\\' + char)
+        item = '"%s"' % item
+    return item
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.