chiark / gitweb /
Don't use generic Exception raises
[fdroidserver.git] / fdroidserver / common.py
index 172e985701f538afa232d63cd7a2fb0c57413cb3..ce3acc12fa3a21bb0ac9d68ca7c9c297b55350c0 100644 (file)
@@ -41,8 +41,8 @@ env = None
 
 def get_default_config():
     return {
-        'sdk_path': os.getenv("ANDROID_HOME"),
-        'ndk_path': os.getenv("ANDROID_NDK"),
+        'sdk_path': os.getenv("ANDROID_HOME") or "",
+        'ndk_path': os.getenv("ANDROID_NDK") or "",
         'build_tools': "20.0.0",
         'ant': "ant",
         'mvn3': "mvn",
@@ -136,6 +136,9 @@ def read_config(opts, config_file='config.py'):
         'android': [
             os.path.join(config['sdk_path'], 'tools', 'android'),
             ],
+        'adb': [
+            os.path.join(config['sdk_path'], 'platform-tools', 'adb'),
+            ],
         }
 
     for b, paths in bin_paths.items():
@@ -173,9 +176,9 @@ def read_config(opts, config_file='config.py'):
 def test_sdk_exists(c):
     if c['sdk_path'] is None:
         # c['sdk_path'] is set to the value of ANDROID_HOME by default
-        logging.critical('No Android SDK found! ANDROID_HOME is not set and sdk_path is not in config.py!')
-        logging.info('You can use ANDROID_HOME to set the path to your SDK, i.e.:')
-        logging.info('\texport ANDROID_HOME=/opt/android-sdk')
+        logging.error('No Android SDK found! ANDROID_HOME is not set and sdk_path is not in config.py!')
+        logging.error('You can use ANDROID_HOME to set the path to your SDK, i.e.:')
+        logging.error('\texport ANDROID_HOME=/opt/android-sdk')
         return False
     if not os.path.exists(c['sdk_path']):
         logging.critical('Android SDK path "' + c['sdk_path'] + '" does not exist!')
@@ -183,9 +186,11 @@ def test_sdk_exists(c):
     if not os.path.isdir(c['sdk_path']):
         logging.critical('Android SDK path "' + c['sdk_path'] + '" is not a directory!')
         return False
-    if not os.path.isdir(os.path.join(c['sdk_path'], 'build-tools')):
-        logging.critical('Android SDK path "' + c['sdk_path'] + '" does not contain "build-tools/"!')
-        return False
+    for d in ['build-tools', 'platform-tools', 'tools']:
+        if not os.path.isdir(os.path.join(c['sdk_path'], d)):
+            logging.critical('Android SDK path "%s" does not contain "%s/"!' % (
+                c['sdk_path'], d))
+            return False
     return True
 
 
@@ -254,9 +259,9 @@ def read_app_args(args, allapps, allow_vercodes=False):
         for p in vercodes:
             if p not in allids:
                 logging.critical("No such package: %s" % p)
-        raise Exception("Found invalid app ids in arguments")
+        raise FDroidException("Found invalid app ids in arguments")
     if not apps:
-        raise Exception("No packages specified")
+        raise FDroidException("No packages specified")
 
     error = False
     for app in apps:
@@ -272,7 +277,7 @@ def read_app_args(args, allapps, allow_vercodes=False):
                     logging.critical("No such vercode %s for app %s" % (v, app['id']))
 
     if error:
-        raise Exception("Found invalid vercodes for some apps")
+        raise FDroidException("Found invalid vercodes for some apps")
 
     return apps
 
@@ -294,7 +299,7 @@ def apknameinfo(filename):
     try:
         result = (m.group(1), m.group(2))
     except AttributeError:
-        raise Exception("Invalid apk name: %s" % filename)
+        raise FDroidException("Invalid apk name: %s" % filename)
     return result
 
 
@@ -392,11 +397,12 @@ class vcs:
                 else:
                     deleterepo = True
                     logging.info(
-                        "Repository details for {0} changed - deleting"
-                        .format(self.local))
+                        "Repository details for %s changed - deleting" % (
+                            self.local))
             else:
                 deleterepo = True
-                logging.info("Repository details missing - deleting")
+                logging.info("Repository details for %s missing - deleting" % (
+                    self.local))
         if deleterepo:
             shutil.rmtree(self.local)
 
@@ -479,11 +485,17 @@ class vcs_git(vcs):
                 # Recreate origin/HEAD as git clone would do it, in case it disappeared
                 p = SilentPopen(['git', 'remote', 'set-head', 'origin', '--auto'], cwd=self.local)
                 if p.returncode != 0:
-                    raise VCSException("Git remote set-head failed", p.output)
+                    lines = p.output.splitlines()
+                    if 'Multiple remote HEAD branches' not in lines[0]:
+                        raise VCSException("Git remote set-head failed", p.output)
+                    branch = lines[1].split(' ')[-1]
+                    p2 = SilentPopen(['git', 'remote', 'set-head', 'origin', branch], cwd=self.local)
+                    if p2.returncode != 0:
+                        raise VCSException("Git remote set-head failed", p.output + '\n' + p2.output)
                 self.refreshed = True
         # origin/HEAD is the HEAD of the remote, e.g. the "default branch" on
         # a github repo. Most of the time this is the same as origin/master.
-        rev = str(rev if rev else 'origin/HEAD')
+        rev = rev or 'origin/HEAD'
         p = SilentPopen(['git', 'checkout', '-f', rev], cwd=self.local)
         if p.returncode != 0:
             raise VCSException("Git checkout of '%s' failed" % rev, p.output)
@@ -601,7 +613,7 @@ class vcs_gitsvn(vcs):
                     raise VCSException("Git svn rebase failed", p.output)
                 self.refreshed = True
 
-        rev = str(rev if rev else 'master')
+        rev = rev or 'master'
         if rev:
             nospaces_rev = rev.replace(' ', '%20')
             # Try finding a svn tag
@@ -610,18 +622,23 @@ class vcs_gitsvn(vcs):
                 # No tag found, normal svn rev translation
                 # Translate svn rev into git format
                 rev_split = rev.split('/')
-                if len(rev_split) > 1:
-                    treeish = 'origin/' + rev_split[0]
-                    svn_rev = rev_split[1]
 
-                else:
-                    # if no branch is specified, then assume trunk (ie. 'master'
-                    # branch):
-                    treeish = 'origin/master'
-                    svn_rev = rev
+                p = None
+                for treeish in ['origin/', '']:
+                    if len(rev_split) > 1:
+                        treeish += rev_split[0]
+                        svn_rev = rev_split[1]
 
-                p = SilentPopen(['git', 'svn', 'find-rev', 'r' + svn_rev, treeish], cwd=self.local)
-                git_rev = p.output.rstrip()
+                    else:
+                        # if no branch is specified, then assume trunk (i.e. 'master' branch):
+                        treeish += 'master'
+                        svn_rev = rev
+
+                    p = SilentPopen(['git', 'svn', 'find-rev', 'r' + svn_rev, treeish], cwd=self.local)
+                    git_rev = p.output.rstrip()
+
+                    if p.returncode == 0 and git_rev:
+                        break
 
                 if p.returncode != 0 or not git_rev:
                     # Try a plain git checkout as a last resort
@@ -716,7 +733,7 @@ class vcs_hg(vcs):
                     raise VCSException("Hg pull failed", p.output)
                 self.refreshed = True
 
-        rev = str(rev if rev else 'default')
+        rev = rev or 'default'
         if not rev:
             return
         p = SilentPopen(['hg', 'update', '-C', rev], cwd=self.local)
@@ -866,7 +883,7 @@ def get_library_references(root_dir):
             relpath = os.path.join(root_dir, path)
             if not os.path.isdir(relpath):
                 continue
-            logging.info("Found subproject at %s" % path)
+            logging.debug("Found subproject at %s" % path)
             libraries.append(path)
     return libraries
 
@@ -884,7 +901,7 @@ def ant_subprojects(root_dir):
 
 def remove_debuggable_flags(root_dir):
     # Remove forced debuggable flags
-    logging.info("Removing debuggable flags")
+    logging.debug("Removing debuggable flags from %s" % root_dir)
     for root, dirs, files in os.walk(root_dir):
         if 'AndroidManifest.xml' in files:
             path = os.path.join(root, 'AndroidManifest.xml')
@@ -970,7 +987,7 @@ def parse_androidmanifests(paths, ignoreversions=None):
     return (max_version, max_vercode, max_package)
 
 
-class _FDroidException(Exception):
+class FDroidException(Exception):
     def __init__(self, value, detail=None):
         self.value = value
         self.detail = detail
@@ -992,11 +1009,11 @@ class _FDroidException(Exception):
         return ret
 
 
-class VCSException(_FDroidException):
+class VCSException(FDroidException):
     pass
 
 
-class BuildException(_FDroidException):
+class BuildException(FDroidException):
     pass
 
 
@@ -1020,7 +1037,7 @@ def getsrclib(spec, srclib_dir, srclibpaths=[], subdir=None,
             name, subdir = name.split('/', 1)
 
     if name not in metadata.srclibs:
-        raise BuildException('srclib ' + name + ' not found.')
+        raise VCSException('srclib ' + name + ' not found.')
 
     srclib = metadata.srclibs[name]
 
@@ -1057,7 +1074,7 @@ def getsrclib(spec, srclib_dir, srclibpaths=[], subdir=None,
                     s_tuple = t
                     break
             if s_tuple is None:
-                raise BuildException('Missing recursive srclib %s for %s' % (
+                raise VCSException('Missing recursive srclib %s for %s' % (
                     lib, name))
             place_srclib(libdir, n, s_tuple[2])
             n += 1
@@ -1340,10 +1357,10 @@ def prepare_source(vcs, app, build, build_dir, srclib_dir, extlib_dir, onserver=
         for d in update_dirs:
             subdir = os.path.join(root_dir, d)
             if d == '.':
-                print("Updating main project")
+                logging.debug("Updating main project")
                 cmd = parms + ['-p', d]
             else:
-                print("Updating subproject %s" % d)
+                logging.debug("Updating subproject %s" % d)
                 cmd = lparms + ['-p', d]
             p = FDroidPopen(cmd, cwd=root_dir)
             # Check to see whether an error was returned without a proper exit
@@ -1649,10 +1666,10 @@ def FDroidPopen(commands, cwd=None, shell=False, output=True):
     while not stdout_reader.eof():
         while not stdout_queue.empty():
             line = stdout_queue.get()
-            if output:
+            if output and options.verbose:
                 # Output directly to console
-                sys.stdout.write(line)
-                sys.stdout.flush()
+                sys.stderr.write(line)
+                sys.stderr.flush()
             result.output += line
 
         time.sleep(0.1)