[ros-vcstools] 05/31: Imported Upstream version 0.1.35

Jochen Sprickerhof jspricke-guest at moszumanska.debian.org
Sun Oct 18 14:23:20 UTC 2015


This is an automated email from the git hooks/post-receive script.

jspricke-guest pushed a commit to branch master
in repository ros-vcstools.

commit ce749f77d6b19d54d72771ad74217780749c068e
Author: Leopold Palomo-Avellaneda <leopold.palomo at upc.edu>
Date:   Fri Nov 28 09:26:07 2014 +0100

    Imported Upstream version 0.1.35
---
 .gitignore                  |   3 ++
 Makefile                    |  22 +---------
 README.rst                  |   7 +++
 dput.cf                     |  24 -----------
 src/vcstools/__version__.py |   2 +-
 src/vcstools/bzr.py         |  10 +++--
 src/vcstools/common.py      | 101 ++++++++++++++++++++++++++++++--------------
 src/vcstools/git.py         |  40 +++++++++++-------
 src/vcstools/hg.py          |  13 +++---
 src/vcstools/svn.py         |  13 +++---
 src/vcstools/tar.py         |  14 +++---
 src/vcstools/vcs_base.py    |  34 ++++++++++-----
 stdeb.cfg => stdeb2.cfg     |   2 +-
 stdeb3.cfg                  |   5 +++
 test/test_bzr.py            |   8 ++++
 test/test_git.py            |  67 +++++++++++++++++++++++++++--
 test/test_hg.py             |   8 ++++
 test/test_svn.py            |   8 ++++
 test/test_tar.py            |   8 ++++
 19 files changed, 261 insertions(+), 128 deletions(-)

diff --git a/.gitignore b/.gitignore
index 8688240..cb0633e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
 *.pyc
 .DS_Store
 .coverage
+build
+dist
+*.egg-info
diff --git a/Makefile b/Makefile
index 794b582..afed6b8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,8 @@
-.PHONY: all setup clean_dist distro clean install deb_dist upload-packages upload-building upload testsetup test
+.PHONY: all setup clean_dist distro clean install testsetup test
 
 NAME=vcstools
 VERSION=$(shell grep version ./src/vcstools/__version__.py | sed 's,version = ,,')
 
-OUTPUT_DIR=deb_dist
-
 
 all:
 	echo "noop for debbuild"
@@ -16,33 +14,17 @@ clean_dist:
 	-rm -f MANIFEST
 	-rm -rf dist
 	-rm -rf deb_dist
+	-rm -fr src/vcstools.egg-info/
 
 distro: clean_dist setup
 	python setup.py sdist
 
-push: distro
-	python setup.py sdist register upload
-	scp dist/${NAME}-${VERSION}.tar.gz ros at ftp-osl.osuosl.org:/home/ros/data/download.ros.org/downloads/${NAME}
-
 clean: clean_dist
 	echo "clean"
 
 install: distro
 	sudo checkinstall python setup.py install
 
-deb_dist:
-	# need to convert unstable to each distro and repeat
-	python setup.py --command-packages=stdeb.command sdist_dsc --workaround-548392=False bdist_deb
-
-upload-packages: deb_dist
-	dput -u -c dput.cf all-shadow-fixed ${OUTPUT_DIR}/${NAME}_${VERSION}-1_amd64.changes 
-	dput -u -c dput.cf all-ros ${OUTPUT_DIR}/${NAME}_${VERSION}-1_amd64.changes 
-
-upload-building: deb_dist
-	dput -u -c dput.cf all-building ${OUTPUT_DIR}/${NAME}_${VERSION}-1_amd64.changes 
-
-upload: upload-building upload-packages
-
 testsetup:
 	echo "running tests"
 
diff --git a/README.rst b/README.rst
index 05ed6e5..11cfbef 100644
--- a/README.rst
+++ b/README.rst
@@ -36,3 +36,10 @@ To run python3 compatibility tests, run either::
 
   $ nosetests3
   $ python3 -m unittest discover --pattern*.py
+
+Test Status
+-----------
+
+.. image:: https://travis-ci.org/vcstools/vcstools.svg?branch=master
+    :target: https://travis-ci.org/vcstools/vcstools
+
diff --git a/dput.cf b/dput.cf
deleted file mode 100644
index ce5e6c7..0000000
--- a/dput.cf
+++ /dev/null
@@ -1,24 +0,0 @@
-[all-building]
-method                  = scp
-login                   = rosbuild
-fqdn                    = repos.ros.org
-incoming                = /var/www/repos/building/queue/all
-run_dinstall            = 0
-post_upload_command     = ssh rosbuild at repos.ros.org -- /usr/bin/reprepro -b /var/www/repos/building --ignore=emptyfilenamepart -V processincoming all
-
-
-[all-shadow-fixed]
-method                  = scp
-login                   = rosbuild
-fqdn                    = repos.ros.org
-incoming                = /var/www/repos/ros-shadow-fixed/ubuntu/queue/all
-run_dinstall            = 0
-post_upload_command     = ssh rosbuild at repos.ros.org -- /usr/bin/reprepro -b /var/www/repos/ros-shadow-fixed/ubuntu --ignore=emptyfilenamepart -V processincoming all
-
-[all-ros]
-method                  = scp
-login                   = rosbuild
-fqdn                    = repos.ros.org
-incoming                = /var/www/repos/ros/ubuntu/queue/all
-run_dinstall            = 0
-post_upload_command     = ssh rosbuild at repos.ros.org -- /usr/bin/reprepro -b /var/www/repos/ros/ubuntu --ignore=emptyfilenamepart -V processincoming all
diff --git a/src/vcstools/__version__.py b/src/vcstools/__version__.py
index 41bf89f..471553d 100644
--- a/src/vcstools/__version__.py
+++ b/src/vcstools/__version__.py
@@ -1 +1 @@
-version = '0.1.32'
+version = '0.1.35'
diff --git a/src/vcstools/bzr.py b/src/vcstools/bzr.py
index b7fc412..703f93d 100644
--- a/src/vcstools/bzr.py
+++ b/src/vcstools/bzr.py
@@ -129,10 +129,12 @@ class BzrClient(VcsClientBase):
                                 break
         return result
 
-    def detect_presence(self):
-        return self.path_exists() and os.path.isdir(os.path.join(self._path, '.bzr'))
+    @staticmethod
+    def static_detect_presence(path):
+        return os.path.isdir(os.path.join(path, '.bzr'))
 
-    def checkout(self, url, version=None, verbose=False, shallow=False):
+    def checkout(self, url, version=None, verbose=False,
+                 shallow=False, timeout=None):
         if url is None or url.strip() == '':
             raise ValueError('Invalid empty url : "%s"' % url)
         # bzr 2.5.1 fails if empty directory exists
@@ -153,7 +155,7 @@ class BzrClient(VcsClientBase):
             return False
         return True
 
-    def update(self, version='', verbose=False):
+    def update(self, version='', verbose=False, timeout=None):
         if not self.detect_presence():
             return False
         value, _, _ = run_shell_command("bzr pull",
diff --git a/src/vcstools/common.py b/src/vcstools/common.py
index c753fa1..8a2a9dc 100644
--- a/src/vcstools/common.py
+++ b/src/vcstools/common.py
@@ -40,17 +40,21 @@ import logging
 import netrc
 import tempfile
 import shutil
+import threading
+import signal
 
 try:
     # py3k
     from urllib.request import urlopen, HTTPPasswordMgrWithDefaultRealm, \
         HTTPBasicAuthHandler, build_opener
     from urllib.parse import urlparse
+    from queue import Queue
 except ImportError:
     # py2.7
     from urlparse import urlparse
     from urllib2 import urlopen, HTTPPasswordMgrWithDefaultRealm, \
         HTTPBasicAuthHandler, build_opener
+    from Queue import Queue
 
 from vcstools.vcs_base import VcsError
 
@@ -68,7 +72,7 @@ def ensure_dir_notexists(path):
         return True
     except OSError as ose:
         # ignore if directory
-        if not ose.errno in [errno.ENOENT, errno.ENOTEMPTY, errno.ENOTDIR]:
+        if ose.errno not in [errno.ENOENT, errno.ENOTEMPTY, errno.ENOTDIR]:
             return False
 
 
@@ -222,8 +226,41 @@ def _discard_line(line):
     return False
 
 
+def _read_shell_output(proc, no_filter, verbose, show_stdout, output_queue):
+    # when we read output in while loop, it would not be returned
+    # in communicate()
+    stdout_buf = []
+    stderr_buf = []
+    if not no_filter:
+        if (verbose or show_stdout):
+            # this loop runs until proc is done it listen to the pipe, print
+            # and stores result in buffer for returning this allows proc to run
+            # while we still can filter out output avoiding readline() because
+            # it may block forever
+            for line in iter(proc.stdout.readline, b''):
+                line = line.decode('UTF-8')
+                if line is not None and line != '':
+                    if verbose or not _discard_line(line):
+                        print(line),
+                        stdout_buf.append(line)
+                if (not line or proc.returncode is not None):
+                    break
+        # stderr was swallowed in pipe, in verbose mode print lines
+        if verbose:
+            for line in iter(proc.stderr.readline, b''):
+                line = line.decode('UTF-8')
+                if line != '':
+                    print(line),
+                    stderr_buf.append(line)
+                if not line:
+                    break
+    output_queue.put(proc.communicate())
+    output_queue.put(stdout_buf)
+    output_queue.put(stderr_buf)
+
+
 def run_shell_command(cmd, cwd=None, shell=False, us_env=True,
-                      show_stdout=False, verbose=False,
+                      show_stdout=False, verbose=False, timeout=None,
                       no_warn=False, no_filter=False):
     """
     executes a command and hides the stdout output, loggs stderr
@@ -236,6 +273,7 @@ def run_shell_command(cmd, cwd=None, shell=False, us_env=True,
     :param show_stdout: show some of the output (except for discarded lines in _discard_line()), ignored if no_filter
     :param no_warn: hides warnings
     :param verbose: show all output, overrides no_warn, ignored if no_filter
+    :param timeout: time allocated to the subprocess
     :param no_filter: does not wrap stdout, so invoked command prints everything outside our knowledge
     this is DANGEROUS, as vulnerable to shell injection.
     :returns: ( returncode, stdout, stderr); stdout is None if no_filter==True
@@ -254,41 +292,42 @@ def run_shell_command(cmd, cwd=None, shell=False, us_env=True,
         else:
             stdout_target = subprocess.PIPE
             stderr_target = subprocess.PIPE
+
+        # additional parameters to Popen when using a timeout
+        crflags = {}
+        if timeout is not None:
+            if hasattr(os.sys, 'winver'):
+                crflags['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP
+            else:
+                crflags['preexec_fn'] = os.setsid
+
         proc = subprocess.Popen(cmd,
                                 shell=shell,
                                 cwd=cwd,
                                 stdout=stdout_target,
                                 stderr=stderr_target,
-                                env=env)
-        # when we read output in while loop, it would not be returned
-        # in communicate()
-        stdout_buf = []
-        stderr_buf = []
-        if not no_filter:
-            if (verbose or show_stdout):
-                # this loop runs until proc is done
-                # it listen to the pipe, print and stores result in buffer for returning
-                # this allows proc to run while we still can filter out output
-                # avoiding readline() because it may block forever
-                for line in iter(proc.stdout.readline, b''):
-                    line = line.decode('UTF-8')
-                    if line is not None and line != '':
-                        if verbose or not _discard_line(line):
-                            print(line),
-                            stdout_buf.append(line)
-                    if (not line or proc.returncode is not None):
-                        break
-            # stderr was swallowed in pipe, in verbose mode print lines
-            if verbose:
-                for line in iter(proc.stderr.readline, b''):
-                    line = line.decode('UTF-8')
-                    if line != '':
-                        print(line),
-                        stderr_buf.append(line)
-                    if not line:
-                        break
+                                env=env,
+                                **crflags)
+
+        # using a queue to enable usage in a separate thread
+        q = Queue()
+        if timeout is None:
+            _read_shell_output(proc, no_filter, verbose, show_stdout, q)
+        else:
+            t = threading.Thread(target=_read_shell_output,
+                                 args=[proc, no_filter, verbose, show_stdout, q])
+            t.start()
+            t.join(timeout)
+            if t.isAlive():
+                if hasattr(os.sys, 'winver'):
+                    os.kill(proc.pid, signal.CTRL_BREAK_EVENT)
+                else:
+                    os.killpg(proc.pid, signal.SIGTERM)
+                t.join()
+        (stdout, stderr) = q.get()
+        stdout_buf = q.get()
+        stderr_buf = q.get()
 
-        (stdout, stderr) = proc.communicate()
         if stdout is not None:
             stdout_buf.append(stdout.decode('utf-8'))
         stdout = "\n".join(stdout_buf)
diff --git a/src/vcstools/git.py b/src/vcstools/git.py
index 760bd15..f507c50 100644
--- a/src/vcstools/git.py
+++ b/src/vcstools/git.py
@@ -156,18 +156,19 @@ class GitClient(VcsClientBase):
             return output.rstrip()
         return None
 
-    def detect_presence(self):
+    @staticmethod
+    def static_detect_presence(path):
         # There is a proposed implementation of detect_presence which might be
         # more future proof, but would depend on parsing the output of git
         # See: https://github.com/vcstools/vcstools/pull/10
-        return self.path_exists() and os.path.exists(os.path.join(self._path, '.git'))
+        return os.path.exists(os.path.join(path, '.git'))
 
-    def checkout(self, url, version=None, verbose=False, shallow=False):
+    def checkout(self, url, version=None, verbose=False, shallow=False, timeout=None):
         """calls git clone and then, if version was given, update(version)"""
         if url is None or url.strip() == '':
             raise ValueError('Invalid empty url : "%s"' % url)
 
-        #since we cannot know whether version names a branch, clone master initially
+        # since we cannot know whether version names a branch, clone master initially
         cmd = 'git clone'
         if shallow:
             cmd += ' --depth 1'
@@ -181,6 +182,7 @@ class GitClient(VcsClientBase):
                                           shell=True,
                                           no_filter=True,
                                           show_stdout=verbose,
+                                          timeout=timeout,
                                           verbose=verbose)
         if value != 0:
             if msg:
@@ -194,13 +196,14 @@ class GitClient(VcsClientBase):
                 return self._do_update(version,
                                        verbose=verbose,
                                        fast_foward=True,
+                                       timeout=timeout,
                                        update_submodules=True)
             else:
                 return True
         except GitError:
             return False
 
-    def update_submodules(self, verbose=False):
+    def update_submodules(self, verbose=False, timeout=None):
 
         # update and or init submodules too
         if LooseVersion(self.gitversion) > LooseVersion('1.7'):
@@ -209,12 +212,13 @@ class GitClient(VcsClientBase):
                                             shell=True,
                                             cwd=self._path,
                                             show_stdout=True,
+                                            timeout=timeout,
                                             verbose=verbose)
             if value != 0:
                 return False
         return True
 
-    def update(self, version=None, verbose=False, force_fetch=False):
+    def update(self, version=None, verbose=False, force_fetch=False, timeout=None):
         """
         if version is None, attempts fast-forwarding current branch, if any.
 
@@ -234,7 +238,7 @@ class GitClient(VcsClientBase):
         try:
             # fetch in any case to get updated tags even if we don't need them
             self._do_fetch()
-            return self._do_update(refname=version, verbose=verbose)
+            return self._do_update(refname=version, verbose=verbose, timeout=timeout)
         except GitError:
             return False
 
@@ -242,6 +246,7 @@ class GitClient(VcsClientBase):
                    refname=None,
                    verbose=False,
                    fast_foward=True,
+                   timeout=None,
                    update_submodules=True):
         '''
         updates without fetching, thus any necessary fetching must be done before
@@ -272,7 +277,8 @@ class GitClient(VcsClientBase):
 
         if not refname:
             # we are neither tracking, nor did we get any refname to update to
-            return (not update_submodules) or self.update_submodules(verbose=verbose)
+            return (not update_submodules) or self.update_submodules(verbose=verbose,
+                                                                     timeout=timeout)
 
         if same_branch:
             if fast_foward:
@@ -300,7 +306,8 @@ class GitClient(VcsClientBase):
             if not refname_is_branch:
                 current_version = self.get_version()
                 if current_version == refname:
-                    return (not update_submodules) or self.update_submodules(verbose=verbose)
+                    return (not update_submodules) or self.update_submodules(verbose=verbose,
+                                                                             timeout=timeout)
 
             if current_branch is None:
                 if not current_version:
@@ -325,7 +332,7 @@ class GitClient(VcsClientBase):
                                                      fetch=False,
                                                      verbose=verbose):
                             return False
-        return (not update_submodules) or self.update_submodules(verbose=verbose)
+        return (not update_submodules) or self.update_submodules(verbose=verbose, timeout=timeout)
 
     def get_version(self, spec=None):
         """
@@ -342,7 +349,7 @@ class GitClient(VcsClientBase):
                 command += " %s" % sanitized(spec)
             command += " --format='%H'"
             output = ''
-            #we repeat the call once after fetching if necessary
+            # we repeat the call once after fetching if necessary
             for _ in range(2):
                 _, output, _ = run_shell_command(command,
                                                  shell=True,
@@ -652,7 +659,7 @@ class GitClient(VcsClientBase):
             os.remove(basepath + '.tar')
         return True
 
-    def _do_fetch(self):
+    def _do_fetch(self, timeout=None):
         """
         calls git fetch
         :raises: GitError when call fails
@@ -662,18 +669,20 @@ class GitClient(VcsClientBase):
                                          cwd=self._path,
                                          shell=True,
                                          no_filter=True,
+                                         timeout=timeout,
                                          show_stdout=True)
-        ## git fetch --tags ONLY fetches new tags and commits used, no other commits!
+        # git fetch --tags ONLY fetches new tags and commits used, no other commits!
         cmd = "git fetch --tags"
         value2, _, _ = run_shell_command(cmd,
                                          cwd=self._path,
                                          shell=True,
                                          no_filter=True,
+                                         timeout=timeout,
                                          show_stdout=True)
         if value1 != 0 or value2 != 0:
             raise GitError('git fetch failed')
 
-    def _do_fast_forward(self, fetch=True, branch_parent=None, verbose=False):
+    def _do_fast_forward(self, branch_parent, fetch=True, verbose=False):
         """Execute git fetch if necessary, and if we can fast-foward,
         do so to the last fetched version using git rebase.
 
@@ -698,6 +707,7 @@ class GitClient(VcsClientBase):
                                       parent_version,
                                       fetch=False):
                 return True
+            print("Cannot fast-forward, local repository and remote '%s' have diverged." % branch_parent)
             return False
         if verbose:
             print("Rebasing repository")
@@ -755,5 +765,5 @@ class GitClient(VcsClientBase):
             raise GitError('Git Checkout failed')
 
 
-#Backwards compatibility
+# Backwards compatibility
 GITClient = GitClient
diff --git a/src/vcstools/hg.py b/src/vcstools/hg.py
index e9aa415..fbd4bdd 100644
--- a/src/vcstools/hg.py
+++ b/src/vcstools/hg.py
@@ -65,7 +65,7 @@ def _get_hg_version():
     return version
 
 
-#hg diff cannot seem to be persuaded to accept a different prefix for filenames
+# hg diff cannot seem to be persuaded to accept a different prefix for filenames
 def _hg_diff_path_change(diff, path):
     """
     Parses hg diff result and changes the filename prefixes.
@@ -138,11 +138,12 @@ class HgClient(VcsClientBase):
             return output.rstrip()
         return None
 
-    def detect_presence(self):
-        return (self.path_exists() and
-                os.path.isdir(os.path.join(self._path, '.hg')))
+    @staticmethod
+    def static_detect_presence(path):
+        return os.path.isdir(os.path.join(path, '.hg'))
 
-    def checkout(self, url, version='', verbose=False, shallow=False):
+    def checkout(self, url, version='', verbose=False,
+                 shallow=False, timeout=None):
         if url is None or url.strip() == '':
             raise ValueError('Invalid empty url : "%s"' % url)
         # make sure that the parent directory exists for #3497
@@ -172,7 +173,7 @@ class HgClient(VcsClientBase):
                 return False
         return True
 
-    def update(self, version='', verbose=False):
+    def update(self, version='', verbose=False, timeout=None):
         verboseflag = ''
         if verbose:
             verboseflag = '--verbose'
diff --git a/src/vcstools/svn.py b/src/vcstools/svn.py
index 78f3edc..2458c71 100755
--- a/src/vcstools/svn.py
+++ b/src/vcstools/svn.py
@@ -93,18 +93,19 @@ class SvnClient(VcsClientBase):
          or None if it cannot be determined
         """
         if self.detect_presence():
-            #3305: parsing not robust to non-US locales
+            # 3305: parsing not robust to non-US locales
             cmd = 'svn info %s' % self._path
             _, output, _ = run_shell_command(cmd, shell=True)
             matches = [l for l in output.splitlines() if l.startswith('URL: ')]
             if matches:
                 return matches[0][5:]
 
-    def detect_presence(self):
-        return self.path_exists() and \
-            os.path.isdir(os.path.join(self.get_path(), '.svn'))
+    @staticmethod
+    def static_detect_presence(path):
+        return os.path.isdir(os.path.join(path, '.svn'))
 
-    def checkout(self, url, version='', verbose=False, shallow=False):
+    def checkout(self, url, version='', verbose=False,
+                 shallow=False, timeout=None):
         if url is None or url.strip() == '':
             raise ValueError('Invalid empty url : "%s"' % url)
         # Need to check as SVN 1.6.17 writes into directory even if not empty
@@ -128,7 +129,7 @@ class SvnClient(VcsClientBase):
             return False
         return True
 
-    def update(self, version=None, verbose=False):
+    def update(self, version=None, verbose=False, timeout=None):
         if not self.detect_presence():
             sys.stderr.write("Error: cannot update non-existing directory\n")
             return False
diff --git a/src/vcstools/tar.py b/src/vcstools/tar.py
index af06272..3b619e8 100644
--- a/src/vcstools/tar.py
+++ b/src/vcstools/tar.py
@@ -67,7 +67,7 @@ class TarClient(VcsClientBase):
     @staticmethod
     def get_environment_metadata():
         metadict = {}
-        metadict["version"] = 'tarfile version: %s' % tarfile.__version__
+        metadict["version"] = 'tarfile version: %s' % tarfile.version
         return metadict
 
     def get_url(self):
@@ -82,10 +82,12 @@ class TarClient(VcsClientBase):
                     return metadata['url']
         return None
 
-    def detect_presence(self):
-        return self.path_exists() and os.path.exists(self.metadata_path)
+    @staticmethod
+    def static_detect_presence(path):
+        return os.path.isfile(os.path.join(path, _METADATA_FILENAME))
 
-    def checkout(self, url, version='', verbose=False, shallow=False):
+    def checkout(self, url, version='', verbose=False,
+                 shallow=False, timeout=None):
         """
         untars tar at url to self.path.
         If version was given, only the subdirectory 'version' of the
@@ -128,7 +130,7 @@ class TarClient(VcsClientBase):
                 raise VcsError("%s is not a subdirectory\n" % subdir)
 
             try:
-                #os.makedirs(os.path.dirname(self._path))
+                # os.makedirs(os.path.dirname(self._path))
                 shutil.move(subdir, self._path)
             except Exception as ex:
                 raise VcsError("%s failed to move %s to %s" % (ex, subdir, self._path))
@@ -144,7 +146,7 @@ class TarClient(VcsClientBase):
                 shutil.rmtree(tempdir)
         return result
 
-    def update(self, version='', verbose=False):
+    def update(self, version='', verbose=False, timeout=None):
         """
         Does nothing except returning true if tar exists in same
         "version" as checked out with vcstools.
diff --git a/src/vcstools/vcs_base.py b/src/vcstools/vcs_base.py
index 2d5aa5e..42343af 100644
--- a/src/vcstools/vcs_base.py
+++ b/src/vcstools/vcs_base.py
@@ -130,48 +130,62 @@ class VcsClientBase(object):
         raise NotImplementedError("Base class get_version method must be overridden for client type %s " %
                                   self._vcs_type_name)
 
-    def checkout(self, url, spec=None, verbose=False, shallow=False):
+    def checkout(self, url, version=None, verbose=False, shallow=False, timeout=None):
         """
         Attempts to create a local repository given a remote
         url. Fails if a target path exists, unless it's an empty directory.
-        If a spec is provided, the local repository
+        If a version is provided, the local repository
         will be updated to that revision. It is possible that
         after a failed call to checkout, a repository still exists,
-        e.g. if an invalid revision spec was given.
+        e.g. if an invalid revision was given.
         If shallow is provided, the scm client may checkout less
         than the full repository history to save time / disk space.
-
+        If a timeout is specified, any pending operation will fail after
+        the specified amount (in seconds). NOTE: this parameter might or
+        might not be honored, depending on VCS client implementation.
         :param url: where to checkout from
         :type url: str
-        :param spec: token for identifying repository revision
-        :type spec: str
+        :param version: token for identifying repository revision
+        :type version: str
         :param shallow: hint to checkout less than a full repository
         :type shallow: bool
+        :param timeout: maximum allocated time to perform operation
+        :type shallow: int
         :returns: True if successful
         """
         raise NotImplementedError("Base class checkout method must be overridden for client type %s " %
                                   self._vcs_type_name)
 
-    def update(self, spec=None, verbose=False):
+    def update(self, version=None, verbose=False, timeout=None):
         """
         Sets the local copy of the repository to a version matching
-        the spec. Fails when there are uncommited changes.
+        the version parameter. Fails when there are uncommited changes.
         On failures (also e.g. network failure) grants the
         checked out files are in the same state as before the call.
+        If a timeout is specified, any pending operation will fail after
+        the specified amount (in seconds)
 
-        :param spec: token for identifying repository revision
+        :param version: token for identifying repository revision
            desired.  Token might be a tagname, branchname, version-id,
            SHA-ID, ... depending on the VCS implementation.
+        :param timeout: maximum allocated time to perform operation
+        :type shallow: int
         :returns: True on success, False else
         """
         raise NotImplementedError("Base class update method must be overridden for client type %s " %
                                   self._vcs_type_name)
 
-    def detect_presence(self):
+    @staticmethod
+    def static_detect_presence(path):
         """For auto detection"""
         raise NotImplementedError(
             "Base class detect_presence method must be overridden")
 
+    def detect_presence(self):
+        """For auto detection"""
+        # call static method
+        return self.static_detect_presence(self._path)
+
     def get_vcs_type_name(self):
         """ used when auto detected """
         return self._vcs_type_name
diff --git a/stdeb.cfg b/stdeb2.cfg
similarity index 61%
rename from stdeb.cfg
rename to stdeb2.cfg
index 577b22e..1165f2c 100644
--- a/stdeb.cfg
+++ b/stdeb2.cfg
@@ -1,4 +1,4 @@
 [DEFAULT]
 Depends: subversion, mercurial, git-core, bzr, python-yaml, python-dateutil
-Suite: lucid oneiric precise quantal raring saucy wheezy
+Suite: lucid oneiric precise quantal raring saucy trusty wheezy jessie
 XS-Python-Version: >= 2.6
diff --git a/stdeb3.cfg b/stdeb3.cfg
new file mode 100644
index 0000000..1c135d2
--- /dev/null
+++ b/stdeb3.cfg
@@ -0,0 +1,5 @@
+[DEFAULT]
+Package: python3-vcstools
+Depends: subversion, mercurial, git-core, bzr, python3-yaml
+Suite: precise quantal raring saucy trusty wheezy jessie
+X-Python3-Version: >= 3.3
diff --git a/test/test_bzr.py b/test/test_bzr.py
index 9e78761..09a6be5 100644
--- a/test/test_bzr.py
+++ b/test/test_bzr.py
@@ -220,6 +220,14 @@ class BzrClientTest(BzrClientTestSetups):
         client = BzrClient(self.remote_path)
         self.assertEquals('', client.get_status())
 
+    def test_get_environment_metadata(self):
+        # Verify that metadata is generated
+        directory = tempfile.mkdtemp()
+        self.directories['local'] = directory
+        local_path = os.path.join(directory, "local")
+        client = BzrClient(local_path)
+        self.assertTrue('version' in client.get_environment_metadata())
+
 
 class BzrClientLogTest(BzrClientTestSetups):
 
diff --git a/test/test_git.py b/test/test_git.py
index 1c133a1..625a391 100644
--- a/test/test_git.py
+++ b/test/test_git.py
@@ -40,10 +40,17 @@ import subprocess
 import tempfile
 import shutil
 import types
+import threading
+import time
 
 from vcstools import GitClient
 from vcstools.vcs_base import VcsError
 
+try:
+    from socketserver import TCPServer, BaseRequestHandler
+except ImportError:
+    from SocketServer import TCPServer, BaseRequestHandler
+
 
 class GitClientTestSetups(unittest.TestCase):
 
@@ -158,11 +165,11 @@ class GitClientTest(GitClientTestSetups):
             self.fetches += 1
             return True
 
-        def iff(self, fetch=True, branch_parent=None, verbose=False):
+        def iff(self, branch_parent, fetch=True, verbose=False):
             self.fast_forwards += 1
             return True
 
-        def isubm(self, verbose=False):
+        def isubm(self, verbose=False, timeout=None):
             self.submodules += 1
             return True
         client._do_fetch = types.MethodType(ifetch, client)
@@ -198,11 +205,11 @@ class GitClientTest(GitClientTestSetups):
             self.fetches += 1
             return True
 
-        def iff(self, fetch=True, branch_parent=None, verbose=False):
+        def iff(self, branch_parent, fetch=True, verbose=False):
             self.fast_forwards += 1
             return True
 
-        def isubm(self, verbose=False):
+        def isubm(self, verbose=False, timeout=None):
             self.submodules += 1
             return True
         client._do_fetch = types.MethodType(ifetch, client)
@@ -357,6 +364,14 @@ class GitClientTest(GitClientTestSetups):
         client = GitClient(self.remote_path)
         self.assertEquals('', client.get_status())
 
+    def test_get_environment_metadata(self):
+        # Verify that metadata is generated
+        directory = tempfile.mkdtemp()
+        self.directories['local'] = directory
+        local_path = os.path.join(directory, "local")
+        client = GitClient(local_path)
+        self.assertTrue('version' in client.get_environment_metadata())
+
 
 class GitClientUpdateTest(GitClientTestSetups):
 
@@ -727,3 +742,47 @@ class GitExportClientTest(GitClientTestSetups):
         self.assertTrue(os.path.exists(self.basepath_export + '.tar.gz'))
         self.assertFalse(os.path.exists(self.basepath_export + '.tar'))
         self.assertFalse(os.path.exists(self.basepath_export))
+
+
+class GitTimeoutTest(unittest.TestCase):
+
+    class MuteHandler(BaseRequestHandler):
+        def handle(self):
+            self.request.recv(1024)
+
+    @classmethod
+    def setUpClass(self):
+        self.mute_server = TCPServer(('localhost', 0), GitTimeoutTest.MuteHandler)
+        _, self.mute_port = self.mute_server.server_address
+        serv_thread = threading.Thread(target=self.mute_server.serve_forever)
+        serv_thread.daemon = True
+        serv_thread.start()
+
+        self.root_directory = tempfile.mkdtemp()
+        self.local_path = os.path.join(self.root_directory, "ros")
+
+
+    def test_checkout_timeout(self):
+        ## SSH'ing to a mute server will hang for a very long time
+        url = 'ssh://test@localhost:{0}/test'.format(self.mute_port)
+        client = GitClient(self.local_path)
+        start = time.time()
+        self.assertFalse(client.checkout(url, timeout=2.0))
+        stop = time.time()
+        self.assertTrue(stop - start > 1.9)
+        self.assertTrue(stop - start < 3.0)
+        # the git processes will clean up the checkout dir, we have to wait
+        # for them to finish in order to avoid a race condition with rmtree()
+        while os.path.exists(self.local_path):
+            time.sleep(0.2)
+
+    @classmethod
+    def tearDownClass(self):
+        self.mute_server.shutdown()
+        if os.path.exists(self.root_directory):
+            shutil.rmtree(self.root_directory)
+
+    def tearDown(self):
+        if os.path.exists(self.local_path):
+            shutil.rmtree(self.local_path)
+
diff --git a/test/test_hg.py b/test/test_hg.py
index 98de8dc..7835f72 100644
--- a/test/test_hg.py
+++ b/test/test_hg.py
@@ -191,6 +191,14 @@ class HGClientTest(HGClientTestSetups):
         client = HgClient(self.remote_path)
         self.assertEquals('', client.get_status())
 
+    def test_get_environment_metadata(self):
+        # Verify that metadata is generated
+        directory = tempfile.mkdtemp()
+        self.directories['local'] = directory
+        local_path = os.path.join(directory, "local")
+        client = HgClient(local_path)
+        self.assertTrue('version' in client.get_environment_metadata())
+
 
 class HGClientLogTest(HGClientTestSetups):
 
diff --git a/test/test_svn.py b/test/test_svn.py
index a2be657..342a441 100644
--- a/test/test_svn.py
+++ b/test/test_svn.py
@@ -184,6 +184,14 @@ class SvnClientTest(SvnClientTestSetups):
         client = SvnClient(self.remote_path)
         self.assertEquals('', client.get_status())
 
+    def test_get_environment_metadata(self):
+        # Verify that metadata is generated
+        directory = tempfile.mkdtemp()
+        self.directories['local'] = directory
+        local_path = os.path.join(directory, "local")
+        client = SvnClient(local_path)
+        self.assertTrue('version' in client.get_environment_metadata())
+
 
 class SvnClientLogTest(SvnClientTestSetups):
 
diff --git a/test/test_tar.py b/test/test_tar.py
index f77b9a0..72d61c0 100644
--- a/test/test_tar.py
+++ b/test/test_tar.py
@@ -128,6 +128,14 @@ class TarClientTest(unittest.TestCase):
         # make sure the tarball subdirectory was promoted correctly.
         self.assertTrue(os.path.exists(os.path.join(local_path, 'stack.xml')))
 
+    def test_get_environment_metadata(self):
+        # Verify that metadata is generated
+        directory = tempfile.mkdtemp()
+        self.directories['local'] = directory
+        local_path = os.path.join(directory, "local")
+        client = TarClient(local_path)
+        self.assertTrue('version' in client.get_environment_metadata())
+
 
 class TarClientTestLocal(unittest.TestCase):
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ros/ros-vcstools.git



More information about the debian-science-commits mailing list