Example #1
0
File: git.py Project: po1/vcstools
    def rev_list_contains(self, refname, version, fetch=True):
        """
        calls git rev-list with refname and returns True if version
        can be found in rev-list result

        :param refname: a git refname
        :param version: an SHA IDs (if partial, caller is responsible
          for mismatch)
        :returns: True if version is an ancestor commit from refname
        :raises: GitError when call to git fetch fails
        """
        # to avoid listing unnecessarily many rev-ids, we cut off all
        # those we are definitely not interested in
        # $ git rev-list foo bar ^baz ^bez
        # means "list all the commits which are reachable from foo or
        # bar, but not from baz or bez". We use --parents because
        # ^baz also excludes baz itself. We could also use git
        # show --format=%P to get all parents first and use that,
        # not sure what's more performant
        if fetch:
            self._do_fetch()
        if (refname is not None and refname != '' and
                version is not None and version != ''):

            cmd = 'git rev-list %s ^%s --parents' % (sanitized(refname), sanitized(version))
            _, output, _ = run_shell_command(cmd, shell=True, cwd=self._path)
            for line in output.splitlines():
                # can have 1, 2 or 3 elements (commit, parent1, parent2)
                for hashid in line.split(" "):
                    if hashid.startswith(version):
                        return True
        return False
Example #2
0
 def checkout(self, url, version='', verbose=False, shallow=False):
     if self.path_exists():
         sys.stderr.write("Error: cannot checkout into existing directory\n")
         return False
     # make sure that the parent directory exists for #3497
     base_path = os.path.split(self.get_path())[0]
     try:
         os.makedirs(base_path)
     except OSError:
         # OSError thrown if directory already exists this is ok
         pass
     cmd = "hg clone %s %s" % (sanitized(url), self._path)
     value, _, _ = run_shell_command(cmd,
                                     shell=True,
                                     no_filter=True)
     if value != 0:
         if self.path_exists():
             sys.stderr.write("Error: cannot checkout into existing directory\n")
         return False
     if version is not None and version.strip() != '':
         cmd = "hg checkout %s" % sanitized(version)
         value, _, _ = run_shell_command(cmd,
                                         cwd=self._path,
                                         shell=True,
                                         no_filter=True)
         if value != 0:
             return False
     return True
Example #3
0
 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
     base_path = os.path.split(self.get_path())[0]
     try:
         os.makedirs(base_path)
     except OSError:
         # OSError thrown if directory already exists this is ok
         pass
     cmd = "hg clone %s %s" % (sanitized(url), self._path)
     value, _, msg = run_shell_command(cmd, shell=True, no_filter=True)
     if value != 0:
         if msg:
             sys.logger.error('%s' % msg)
         return False
     if version is not None and version.strip() != '':
         cmd = "hg checkout %s" % sanitized(version)
         value, _, msg = run_shell_command(cmd,
                                           cwd=self._path,
                                           shell=True,
                                           no_filter=True)
         if value != 0:
             if msg:
                 sys.stderr.write('%s\n' % msg)
             return False
     return True
Example #4
0
 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
     if not ensure_dir_notexists(self.get_path()):
         self.logger.error("Can't remove %s" % self.get_path())
         return False
     if version is not None and version != '':
         if not version.startswith("-r"):
             version = "-r%s" % version
     elif version is None:
         version = ''
     cmd = 'svn co %s %s %s' % (sanitized(version), sanitized(url),
                                self._path)
     value, _, msg = run_shell_command(cmd, shell=True, no_filter=True)
     if value != 0:
         if msg:
             self.logger.error('%s' % msg)
         return False
     return True
Example #5
0
    def _rev_list_contains(self, refname, version, fetch=True):
        """
        calls git rev-list with refname and returns True if version
        can be found in rev-list result

        :param refname: a git refname
        :param version: an SHA IDs (if partial, caller is responsible
          for mismatch)
        :returns: True if version is an ancestor commit from refname
        :raises: GitError when call to git fetch fails
        """
        # to avoid listing unnecessarily many rev-ids, we cut off all
        # those we are definitely not interested in
        # $ git rev-list foo bar ^baz ^bez
        # means "list all the commits which are reachable from foo or
        # bar, but not from baz or bez". We use --parents because
        # ^baz also excludes baz itself. We could also use git
        # show --format=%P to get all parents first and use that,
        # not sure what's more performant
        if fetch:
            self._do_fetch()
        if (refname is not None and refname != '' and version is not None
                and version != ''):

            cmd = 'git rev-list %s ^%s --parents' % (sanitized(refname),
                                                     sanitized(version))
            _, output, _ = run_shell_command(cmd, shell=True, cwd=self._path)
            for line in output.splitlines():
                # can have 1, 2 or 3 elements (commit, parent1, parent2)
                for hashid in line.split(" "):
                    if hashid.startswith(version):
                        return True
        return False
Example #6
0
 def checkout(self, url, version='', verbose=False, shallow=False):
     if url is None or url.strip() == '':
         raise ValueError('Invalid empty url : "%s"' % url)
     # make sure that the parent directory exists for #3497
     base_path = os.path.split(self.get_path())[0]
     try:
         os.makedirs(base_path)
     except OSError:
         # OSError thrown if directory already exists this is ok
         pass
     cmd = "hg clone %s %s" % (sanitized(url), self._path)
     value, _, msg = run_shell_command(cmd,
                                       shell=True,
                                       no_filter=True)
     if value != 0:
         if msg:
             sys.logger.error('%s' % msg)
         return False
     if version is not None and version.strip() != '':
         cmd = "hg checkout %s" % sanitized(version)
         value, _, msg = run_shell_command(cmd,
                                         cwd=self._path,
                                         shell=True,
                                         no_filter=True)
         if value != 0:
             if msg:
                 sys.stderr.write('%s\n' % msg)
             return False
     return True
Example #7
0
 def get_version(self, spec=None):
     """
     :param spec: (optional) token to identify desired version. For
       git, this may be anything accepted by git log, e.g. a tagname,
       branchname, or sha-id.
     :param fetch: When spec is given, can be used to suppress git fetch call
     :returns: current SHA-ID of the repository. Or if spec is
       provided, the SHA-ID of a commit specified by some token if found, else None
     """
     if self.detect_presence():
         command = "git log -1"
         if spec is not None:
             command += " %s" % sanitized(spec)
         command += " --format='%H'"
         repeated = False
         output = ''
         #we repeat the call once after fetching if necessary
         for _ in range(2):
             _, output, _ = run_shell_command(command,
                                              shell=True,
                                              cwd=self._path)
             if (output != '' or spec is None):
                 break
             # we try again after fetching if given spec had not been found
             try:
                 self._do_fetch()
             except GitError:
                 return None
         # On Windows the version can have single quotes around it
         output = output.strip("'")
         return output
     return None
Example #8
0
File: git.py Project: po1/vcstools
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath is None:
            relpath = ''

        if self.path_exists() and os.path.exists(os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = (("-n %d" % (int(limit))) if limit else "")

            GIT_COMMIT_FIELDS = ['id', 'author', 'email', 'date', 'message']
            GIT_LOG_FORMAT = '%x1f'.join(['%H', '%an', '%ae', '%ad', '%s']) + '%x1e'

            command = "git --work-tree=%s log --format=\"%s\" %s %s " % (self._path, GIT_LOG_FORMAT,
                                                                         limit_cmd, sanitized(relpath))
            return_code, response_str, stderr = run_shell_command(command, shell=True, cwd=self._path)

            if return_code == 0:
                # Parse response
                response = response_str.strip('\n\x1e').split("\x1e")
                response = [row.strip().split("\x1f") for row in response]
                response = [dict(zip(GIT_COMMIT_FIELDS, row)) for row in response]

                # Parse dates
                for entry in response:
                    entry['date'] = dateutil.parser.parse(entry['date'])

        return response
Example #9
0
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath is None:
            relpath = ""

        if self.path_exists() and os.path.exists(os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = ("--limit %d" % (int(limit))) if limit else ""
            HG_COMMIT_FIELDS = ["id", "author", "email", "date", "message"]
            HG_LOG_FORMAT = (
                "\x1f".join(["{node|short}", "{author|person}", "{autor|email}", "{date|isodate}", "{desc}"]) + "\x1e"
            )

            command = "hg log %s --template '%s' %s" % (sanitized(relpath), HG_LOG_FORMAT, limit_cmd)

            return_code, response_str, stderr = run_shell_command(command, shell=True, cwd=self._path)

            if return_code == 0:
                # Parse response
                response = response_str.strip("\n\x1e").split("\x1e")
                response = [row.strip().split("\x1f") for row in response]
                response = [dict(zip(HG_COMMIT_FIELDS, row)) for row in response]
                # Parse dates
                for entry in response:
                    entry["date"] = dateutil.parser.parse(entry["date"])

        return response
Example #10
0
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath is None:
            relpath = ""

        # Compile regexes
        id_regex = re.compile("^revno: ([0-9]+)$", flags=re.MULTILINE)
        committer_regex = re.compile("^committer: (.+)$", flags=re.MULTILINE)
        timestamp_regex = re.compile("^timestamp: (.+)$", flags=re.MULTILINE)
        message_regex = re.compile("^  (.+)$", flags=re.MULTILINE)

        if self.path_exists() and os.path.exists(os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = ("--limit=%d" % (int(limit))) if limit else ""
            command = "bzr log %s %s" % (sanitized(relpath), limit_cmd)
            return_code, text_response, stderr = run_shell_command(command, shell=True, cwd=self._path)
            if return_code == 0:
                revno_match = id_regex.findall(text_response)
                committer_match = committer_regex.findall(text_response)
                timestamp_match = timestamp_regex.findall(text_response)
                message_match = message_regex.findall(text_response)

                # Extract the entries
                for revno, committer, timestamp, message in zip(
                    revno_match, committer_match, timestamp_match, message_match
                ):
                    author, email_address = email.utils.parseaddr(committer)
                    date = dateutil.parser.parse(timestamp)
                    log_data = {"id": revno, "author": author, "email": email_address, "message": message, "date": date}

                    response.append(log_data)

        return response
Example #11
0
File: git.py Project: po1/vcstools
 def get_version(self, spec=None):
     """
     :param spec: (optional) token to identify desired version. For
       git, this may be anything accepted by git log, e.g. a tagname,
       branchname, or sha-id.
     :param fetch: When spec is given, can be used to suppress git fetch call
     :returns: current SHA-ID of the repository. Or if spec is
       provided, the SHA-ID of a commit specified by some token if found, else None
     """
     if self.detect_presence():
         command = "git log -1"
         if spec is not None:
             command += " %s" % sanitized(spec)
         command += " --format='%H'"
         output = ''
         #we repeat the call once after fetching if necessary
         for _ in range(2):
             _, output, _ = run_shell_command(command,
                                              shell=True,
                                              cwd=self._path)
             if (output != '' or spec is None):
                 break
             # we try again after fetching if given spec had not been found
             try:
                 self._do_fetch()
             except GitError:
                 return None
         # On Windows the version can have single quotes around it
         output = output.strip("'")
         return output
     return None
Example #12
0
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath is None:
            relpath = ''

        if self.path_exists() and os.path.exists(os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = (("--limit %d" % (int(limit))) if limit else "")
            command = "svn log %s --xml %s" % (limit_cmd, sanitized(relpath) if len(relpath) > 0 else '')
            return_code, xml_response, stderr = run_shell_command(command, shell=True, cwd=self._path)

            # Parse response
            dom = xml.dom.minidom.parseString(xml_response)
            log_entries = dom.getElementsByTagName("logentry")

            # Extract the entries
            for log_entry in log_entries:
                author_tag = log_entry.getElementsByTagName("author")[0]
                date_tag = log_entry.getElementsByTagName("date")[0]
                msg_tags = log_entry.getElementsByTagName("msg")

                log_data = dict()
                log_data['id'] = log_entry.getAttribute("revision")
                log_data['author'] = author_tag.firstChild.nodeValue
                log_data['email'] = None
                log_data['date'] = dateutil.parser.parse(str(date_tag.firstChild.nodeValue))
                if len(msg_tags) > 0 and msg_tags[0].firstChild:
                    log_data['message'] = msg_tags[0].firstChild.nodeValue
                else:
                    log_data['message'] = ''

                response.append(log_data)

        return response
Example #13
0
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath == None:
            relpath = ''

        if self.path_exists() and os.path.exists(os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = (("--limit %d" % (int(limit))) if limit else "")
            HG_COMMIT_FIELDS = ['id', 'author', 'email', 'date', 'message']
            HG_LOG_FORMAT = '\x1f'.join(['{node|short}', '{author|person}',
                                         '{autor|email}', '{date|isodate}',
                                         '{desc}']) + '\x1e'

            command = "hg log %s --template '%s' %s" % (sanitized(relpath),
                                                        HG_LOG_FORMAT,
                                                        limit_cmd)

            return_code, response_str, stderr = run_shell_command(command, shell=True, cwd=self._path)

            if return_code == 0:
                # Parse response
                response = response_str.strip('\n\x1e').split("\x1e")
                response = [row.strip().split("\x1f") for row in response]
                response = [dict(zip(HG_COMMIT_FIELDS, row)) for row in response]
                print(response)
                # Parse dates
                for entry in response:
                    entry['date'] = dateutil.parser.parse(entry['date'])

        return response
Example #14
0
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath == None:
            relpath = ""

        if self.path_exists() and os.path.exists(os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = ("-n %d" % (int(limit))) if limit else ""

            GIT_COMMIT_FIELDS = ["id", "author", "email", "date", "message"]
            GIT_LOG_FORMAT = "%x1f".join(["%H", "%an", "%ae", "%ad", "%s"]) + "%x1e"

            command = 'git --work-tree=%s log --format="%s" %s %s ' % (
                self._path,
                GIT_LOG_FORMAT,
                limit_cmd,
                sanitized(relpath),
            )
            return_code, response, stderr = run_shell_command(command, shell=True, cwd=self._path)

            if return_code == 0:
                # Parse response
                response = response.strip("\n\x1e").split("\x1e")
                response = [row.strip().split("\x1f") for row in response]
                response = [dict(zip(GIT_COMMIT_FIELDS, row)) for row in response]

            # Parse dates
            for entry in response:
                entry["date"] = dateutil.parser.parse(entry["date"])

        return response
Example #15
0
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath == None:
            relpath = ''

        if self.path_exists() and os.path.exists(os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = (("--limit %d" % (int(limit))) if limit else "")
            command = "svn log %s --xml %s" % (limit_cmd, sanitized(relpath) if len(relpath) > 0 else '')
            return_code, xml_response, stderr = run_shell_command(command, shell=True, cwd=self._path)

            # Parse response
            dom = xml.dom.minidom.parseString(xml_response)
            log_entries = dom.getElementsByTagName("logentry")

            # Extract the entries
            for log_entry in log_entries:
                author_tag = log_entry.getElementsByTagName("author")[0]
                date_tag = log_entry.getElementsByTagName("date")[0]
                msg_tags = log_entry.getElementsByTagName("msg")

                log_data = dict()
                log_data['id'] = log_entry.getAttribute("revision")
                log_data['author'] = author_tag.firstChild.nodeValue
                log_data['email'] = None
                log_data['date'] = dateutil.parser.parse(str(date_tag.firstChild.nodeValue))
                if len(msg_tags) > 0:
                    log_data['message'] = msg_tags[0].firstChild.nodeValue

                response.append(log_data)

        return response
Example #16
0
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath is None:
            relpath = ''

        if self.path_exists() and os.path.exists(
                os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = (("-n %d" % (int(limit))) if limit else "")

            GIT_COMMIT_FIELDS = ['id', 'author', 'email', 'date', 'message']
            GIT_LOG_FORMAT = '%x1f'.join(['%H', '%an', '%ae', '%ad', '%s'
                                          ]) + '%x1e'

            command = "git --work-tree=%s log --format=\"%s\" %s %s " % (
                self._path, GIT_LOG_FORMAT, limit_cmd, sanitized(relpath))
            return_code, response_str, stderr = run_shell_command(
                command, shell=True, cwd=self._path)

            if return_code == 0:
                # Parse response
                response = response_str.strip('\n\x1e').split("\x1e")
                response = [row.strip().split("\x1f") for row in response]
                response = [
                    dict(zip(GIT_COMMIT_FIELDS, row)) for row in response
                ]

                # Parse dates
                for entry in response:
                    entry['date'] = dateutil.parser.parse(entry['date'])

        return response
Example #17
0
 def get_version(self, spec=None):
     """
     :param spec: (optional) revisionspec of desired version.  May
       be any revisionspec as returned by 'bzr help revisionspec',
       e.g. a tagname or 'revno:<number>'
     :returns: the current revision number of the repository. Or if
       spec is provided, the number of a revision specified by some
       token.
     """
     if self.detect_presence():
         if spec is not None:
             command = ['bzr log -r %s .' % sanitized(spec)]
             _, output, _ = run_shell_command(command,
                                              shell=True,
                                              cwd=self._path,
                                              us_env=True)
             if output is None or output.strip() == '' or output.startswith("bzr:"):
                 return None
             else:
                 matches = [l for l in output.split('\n') if l.startswith('revno: ')]
                 if len(matches) == 1:
                     return matches[0].split()[1]
         else:
             _, output, _ = run_shell_command('bzr revno --tree',
                                              shell=True,
                                              cwd=self._path,
                                              us_env=True)
             return output.strip()
Example #18
0
 def get_version(self, spec=None):
     """
     :param spec: (optional) revisionspec of desired version.  May
       be any revisionspec as returned by 'bzr help revisionspec',
       e.g. a tagname or 'revno:<number>'
     :returns: the current revision number of the repository. Or if
       spec is provided, the number of a revision specified by some
       token.
     """
     if self.detect_presence():
         if spec is not None:
             _, output, _ = run_shell_command('bzr log -r %s .' %
                                              sanitized(spec),
                                              shell=True,
                                              cwd=self._path,
                                              us_env=True)
             if output is None or output.strip() == '' or output.startswith(
                     "bzr:"):
                 return None
             else:
                 matches = [
                     l for l in output.split('\n')
                     if l.startswith('revno: ')
                 ]
                 if len(matches) == 1:
                     return matches[0].split()[1]
         else:
             _, output, _ = run_shell_command('bzr revno --tree',
                                              shell=True,
                                              cwd=self._path,
                                              us_env=True)
             return output.strip()
Example #19
0
    def _get_branch_parent(self, fetch=False, current_branch=None):
        """
        :param fetch: if true, performs git fetch first
        :param current_branch: if not None, this is used as current branch (else extra shell call)
        :returns: (branch, remote) the name of the branch this branch tracks and its remote
        :raises: GitError if fetch fails
        """
        if not self.path_exists():
            return (None, None)
        # get name of configured merge ref.
        branchname = current_branch or self._get_branch()
        if branchname is None:
            return (None, None)

        cmd = 'git config --get %s' % sanitized('branch.%s.merge' % branchname)

        _, output, _ = run_shell_command(cmd,
                                         shell=True,
                                         cwd=self._path)
        if not output:
            return (None, None)
        lines = output.splitlines()
        if len(lines) > 1:
            sys.stderr.write("vcstools unable to handle multiple merge references for branch %s:\n%s\n"
                             % (branchname, output))
            return (None, None)

        # get name of configured remote
        cmd = 'git config --get "branch.%s.remote"' % branchname
        _, output2, _ = run_shell_command(cmd, shell=True, cwd=self._path)
        remote = output2 or self._get_default_remote()

        branch_reference = lines[0]
        # branch_reference is either refname, or /refs/heads/refname, or
        # heads/refname we would like to return refname however,
        # user could also have named any branch
        # "/refs/heads/refname", for some unholy reason check all
        # known branches on remote for refname, then for the odd
        # cases, as git seems to do
        candidate = branch_reference
        if candidate.startswith('refs/'):
            candidate = candidate[len('refs/'):]
        if candidate.startswith('heads/'):
            candidate = candidate[len('heads/'):]
        elif candidate.startswith('tags/'):
            candidate = candidate[len('tags/'):]
        elif candidate.startswith('remotes/'):
            candidate = candidate[len('remotes/'):]

        result = None
        if self._is_remote_branch(candidate, remote_name=remote, fetch=fetch):
            result = candidate
        elif branch_reference != candidate and self._is_remote_branch(branch_reference,
                                                                      remote_name=remote,
                                                                      fetch=False):
            result = branch_reference

        if result is not None:
            return (result, remote)
        return None, None
Example #20
0
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath is None:
            relpath = ''

        if self.path_exists() and os.path.exists(
                os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = (("--limit %d" % (int(limit))) if limit else "")
            HG_COMMIT_FIELDS = ['id', 'author', 'email', 'date', 'message']
            HG_LOG_FORMAT = '\x1f'.join([
                '{node|short}', '{author|person}', '{autor|email}',
                '{date|isodate}', '{desc}'
            ]) + '\x1e'

            command = "hg log %s --template '%s' %s" % (
                sanitized(relpath), HG_LOG_FORMAT, limit_cmd)

            return_code, response_str, stderr = run_shell_command(
                command, shell=True, cwd=self._path)

            if return_code == 0:
                # Parse response
                response = response_str.strip('\n\x1e').split("\x1e")
                response = [row.strip().split("\x1f") for row in response]
                response = [
                    dict(zip(HG_COMMIT_FIELDS, row)) for row in response
                ]
                # Parse dates
                for entry in response:
                    entry['date'] = dateutil.parser.parse(entry['date'])

        return response
Example #21
0
 def get_diff(self, basepath=None):
     response = ''
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         # git needs special treatment as it only works from inside
         # use HEAD to also show staged changes. Maybe should be option?
         # injection should be impossible using relpath, but to be sure, we check
         cmd = "git diff HEAD --src-prefix=%s/ --dst-prefix=%s/ ." % \
               (sanitized(rel_path), sanitized(rel_path))
         _, response, _ = run_shell_command(cmd, shell=True, cwd=self._path)
         if LooseVersion(self.gitversion) > LooseVersion('1.7'):
             cmd = 'git submodule foreach --recursive git diff HEAD'
             _, output, _ = run_shell_command(cmd, shell=True, cwd=self._path)
             response += _git_diff_path_submodule_change(output, rel_path)
     return response
Example #22
0
File: git.py Project: po1/vcstools
 def get_diff(self, basepath=None):
     response = ''
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         # git needs special treatment as it only works from inside
         # use HEAD to also show staged changes. Maybe should be option?
         # injection should be impossible using relpath, but to be sure, we check
         cmd = "git diff HEAD --src-prefix=%s/ --dst-prefix=%s/ ." % \
               (sanitized(rel_path), sanitized(rel_path))
         _, response, _ = run_shell_command(cmd, shell=True, cwd=self._path)
         if LooseVersion(self.gitversion) > LooseVersion('1.7'):
             cmd = 'git submodule foreach --recursive git diff HEAD'
             _, output, _ = run_shell_command(cmd, shell=True, cwd=self._path)
             response += _git_diff_path_submodule_change(output, rel_path)
     return response
Example #23
0
    def _get_branch_parent(self, fetch=False, current_branch=None):
        """
        :param fetch: if true, performs git fetch first
        :param current_branch: if not None, this is used as current branch (else extra shell call)
        :returns: (branch, remote) the name of the branch this branch tracks and its remote
        :raises: GitError if fetch fails
        """
        if not self.path_exists():
            return (None, None)
        # get name of configured merge ref.
        branchname = current_branch or self._get_branch()
        if branchname is None:
            return (None, None)

        cmd = 'git config --get %s' % sanitized('branch.%s.merge' % branchname)

        _, output, _ = run_shell_command(cmd, shell=True, cwd=self._path)
        if not output:
            return (None, None)
        lines = output.splitlines()
        if len(lines) > 1:
            sys.stderr.write(
                "vcstools unable to handle multiple merge references for branch %s:\n%s\n"
                % (branchname, output))
            return (None, None)

        # get name of configured remote
        cmd = 'git config --get "branch.%s.remote"' % branchname
        _, output2, _ = run_shell_command(cmd, shell=True, cwd=self._path)
        remote = output2 or self._get_default_remote()

        branch_reference = lines[0]
        # branch_reference is either refname, or /refs/heads/refname, or
        # heads/refname we would like to return refname however,
        # user could also have named any branch
        # "/refs/heads/refname", for some unholy reason check all
        # known branches on remote for refname, then for the odd
        # cases, as git seems to do
        candidate = branch_reference
        if candidate.startswith('refs/'):
            candidate = candidate[len('refs/'):]
        if candidate.startswith('heads/'):
            candidate = candidate[len('heads/'):]
        elif candidate.startswith('tags/'):
            candidate = candidate[len('tags/'):]
        elif candidate.startswith('remotes/'):
            candidate = candidate[len('remotes/'):]

        result = None
        if self._is_remote_branch(candidate, remote_name=remote, fetch=fetch):
            result = candidate
        elif branch_reference != candidate and self._is_remote_branch(
                branch_reference, remote_name=remote, fetch=False):
            result = branch_reference

        if result is not None:
            return (result, remote)
        return None, None
Example #24
0
 def get_diff(self, basepath=None):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = sanitized(normalized_rel_path(self._path, basepath))
         command = "bzr diff %s" % rel_path
         command += " -p1 --prefix %s/:%s/" % (rel_path, rel_path)
         _, response, _ = run_shell_command(command, shell=True, cwd=basepath)
     return response
 def get_diff(self, basepath=None):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = sanitized(normalized_rel_path(self._path, basepath))
         command = "bzr diff %s" % rel_path
         command += " -p1 --prefix %s/:%s/" % (rel_path, rel_path)
         _, response, _ = run_shell_command(command, shell=True, cwd=basepath)
     return response
Example #26
0
 def _get_version_from_path(self, spec=None, path=None):
     """
     :param spec: (optional) spec can be what 'svn info --help'
       allows, meaning a revnumber, {date}, HEAD, BASE, PREV, or
       COMMITTED.
     :param path: the url to use, default is for this repo
     :returns: current revision number of the repository. Or if spec
       provided, the number of a revision specified by some
       token.
     """
     if not self.path_exists():
         return None
     command = 'svn info '
     if spec is not None:
         if spec.isdigit():
             # looking up svn with "-r" takes long, and if spec is
             # a number, all we get from svn is the same number,
             # unless we try to look at higher rev numbers (in
             # which case either get the same number, or an error
             # if the rev does not exist). So we first do a very
             # quick svn info, and check revision numbers.
             currentversion = self.get_version(spec=None)
             # currentversion is like '-r12345'
             if currentversion is not None and \
                int(currentversion[2:]) > int(spec):
                 # so if we know revision exist, just return the
                 # number, avoid the long call to svn server
                 return '-r' + spec
         if spec.startswith("-r"):
             command += sanitized(spec)
         else:
             command += sanitized('-r%s' % spec)
     command += " %s" % path
     # #3305: parsing not robust to non-US locales
     _, output, _ = run_shell_command(command, shell=True, us_env=True)
     if output is not None:
         matches = \
             [l for l in output.splitlines() if l.startswith('Last Changed Rev: ')]
         if len(matches) == 1:
             split_str = matches[0].split()
             if len(split_str) == 4:
                 return '-r' + split_str[3]
     return None
Example #27
0
 def get_diff(self, basepath=None):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         command = "hg diff -g %(path)s --repository %(path)s" % {'path': sanitized(rel_path)}
         _, response, _ = run_shell_command(command, shell=True, cwd=basepath)
         response = _hg_diff_path_change(response, rel_path)
     return response
Example #28
0
 def get_diff(self, basepath=None):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         command = 'svn diff %s' % sanitized(rel_path)
         _, response, _ = run_shell_command(command,
                                            shell=True,
                                            cwd=basepath)
     return response
 def get_diff(self, basepath=None):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         command = 'svn diff %s' % sanitized(rel_path)
         _, response, _ = run_shell_command(command,
                                            shell=True,
                                            cwd=basepath)
     return response
Example #30
0
 def checkout(self, url, version='', verbose=False, shallow=False):
     # Need to check as SVN does not care
     if self.path_exists():
         sys.stderr.write("Error: cannot checkout into existing "
                        + "directory %s\n" % self._path)
         return False
     if version is not None and version != '':
         if not version.startswith("-r"):
             version = "-r%s" % version
     elif version is None:
         version = ''
     cmd = 'svn co %s %s %s' % (sanitized(version),
                                sanitized(url),
                                self._path)
     value, _, _ = run_shell_command(cmd,
                                     shell=True,
                                     no_filter=True)
     if value == 0:
         return True
     return False
Example #31
0
    def get_branch_parent(self, fetch=False, current_branch=None):
        """
        return the name of the branch this branch tracks, if any

        :raises: GitError if fetch fails
        """
        if self.path_exists():
            # get name of configured merge ref.
            branchname = current_branch or self.get_branch()
            if branchname is None:
                return None
            cmd = 'git config --get %s' % sanitized(
                'branch.%s.merge' % branchname)

            _, output, _ = run_shell_command(cmd, shell=True, cwd=self._path)
            if not output:
                return None
            lines = output.splitlines()
            if len(lines) > 1:
                print(
                    "vcstools unable to handle multiple merge references for branch %s:\n%s"
                    % (branchname, output))
                return None
            # get name of configured remote
            cmd = 'git config --get "branch.%s.remote"' % branchname
            _, output2, _ = run_shell_command(cmd, shell=True, cwd=self._path)
            if output2 != "origin":
                print(
                    "vcstools only handles branches tracking remote 'origin', branch '%s' tracks remote '%s'"
                    % (branchname, output2))
                return None
            output = lines[0]
            # output is either refname, or /refs/heads/refname, or
            # heads/refname we would like to return refname however,
            # user could also have named any branch
            # "/refs/heads/refname", for some unholy reason check all
            # known branches on remote for refname, then for the odd
            # cases, as git seems to do
            candidate = output
            if candidate.startswith('refs/'):
                candidate = candidate[len('refs/'):]
            if candidate.startswith('heads/'):
                candidate = candidate[len('heads/'):]
            elif candidate.startswith('tags/'):
                candidate = candidate[len('tags/'):]
            elif candidate.startswith('remotes/'):
                candidate = candidate[len('remotes/'):]
            if self.is_remote_branch(candidate, fetch=fetch):
                return candidate
            if output != candidate and self.is_remote_branch(output,
                                                             fetch=False):
                return output
        return None
Example #32
0
 def get_diff(self, basepath=None):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         command = "hg diff -g %(path)s --repository %(path)s" % {
             'path': sanitized(rel_path)
         }
         _, response, _ = run_shell_command(command,
                                            shell=True,
                                            cwd=basepath)
         response = _hg_diff_path_change(response, rel_path)
     return response
Example #33
0
 def is_tag(self, tag_name, fetch=True):
     """
     checks list of tags for match.
     Set fetch to False if you just fetched already.
     """
     if fetch:
         self._do_fetch()
     if self.path_exists():
         cmd = "git tag -l %s" % sanitized(tag_name)
         _, output, _ = run_shell_command(cmd, shell=True, cwd=self._path)
         lines = output.splitlines()
         if len(lines) == 1:
             return True
     return False
Example #34
0
File: git.py Project: po1/vcstools
    def get_branch_parent(self, fetch=False, current_branch=None):
        """
        return the name of the branch this branch tracks, if any

        :raises: GitError if fetch fails
        """
        if self.path_exists():
            # get name of configured merge ref.
            branchname = current_branch or self.get_branch()
            if branchname is None:
                return None
            cmd = 'git config --get %s' % sanitized('branch.%s.merge' % branchname)

            _, output, _ = run_shell_command(cmd,
                                             shell=True,
                                             cwd=self._path)
            if not output:
                return None
            lines = output.splitlines()
            if len(lines) > 1:
                print("vcstools unable to handle multiple merge references for branch %s:\n%s" % (branchname, output))
                return None
            # get name of configured remote
            cmd = 'git config --get "branch.%s.remote"' % branchname
            _, output2, _ = run_shell_command(cmd, shell=True, cwd=self._path)
            if output2 != "origin":
                print("vcstools only handles branches tracking remote 'origin'," +
                      " branch '%s' tracks remote '%s'" % (branchname, output2))
                return None
            output = lines[0]
            # output is either refname, or /refs/heads/refname, or
            # heads/refname we would like to return refname however,
            # user could also have named any branch
            # "/refs/heads/refname", for some unholy reason check all
            # known branches on remote for refname, then for the odd
            # cases, as git seems to do
            candidate = output
            if candidate.startswith('refs/'):
                candidate = candidate[len('refs/'):]
            if candidate.startswith('heads/'):
                candidate = candidate[len('heads/'):]
            elif candidate.startswith('tags/'):
                candidate = candidate[len('tags/'):]
            elif candidate.startswith('remotes/'):
                candidate = candidate[len('remotes/'):]
            if self.is_remote_branch(candidate, fetch=fetch):
                return candidate
            if output != candidate and self.is_remote_branch(output, fetch=False):
                return output
        return None
Example #35
0
 def checkout(self, url, version='', verbose=False, shallow=False):
     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
     if not ensure_dir_notexists(self.get_path()):
         self.logger.error("Can't remove %s" % self.get_path())
         return False
     if version is not None and version != '':
         if not version.startswith("-r"):
             version = "-r%s" % version
     elif version is None:
         version = ''
     cmd = 'svn co %s %s %s' % (sanitized(version),
                                sanitized(url),
                                self._path)
     value, _, msg = run_shell_command(cmd,
                                       shell=True,
                                       no_filter=True)
     if value != 0:
         if msg:
             self.logger.error('%s' % msg)
         return False
     return True
Example #36
0
    def get_version(self, spec=None):
        """
        :param spec: (optional) token for identifying version. spec can be
          a whatever is allowed by 'hg log -r', e.g. a tagname, sha-ID,
          revision-number
        :returns: the current SHA-ID of the repository. Or if spec is
          provided, the SHA-ID of a revision specified by some
          token.
        """
        # detect presence only if we need path for cwd in popen
        if spec is not None:
            if self.detect_presence():
                command = 'hg log -r %s' % sanitized(spec)
                repeated = False
                output = ''
                # we repeat the call once after pullin if necessary
                while output == '':
                    _, output, _ = run_shell_command(command,
                                                     shell=True,
                                                     cwd=self._path,
                                                     us_env=True)
                    if (output.strip() != '' and not output.startswith("abort")
                            or repeated is True):

                        matches = [
                            l for l in output.splitlines()
                            if l.startswith('changeset: ')
                        ]
                        if len(matches) == 1:
                            return matches[0].split(':')[2]
                        else:
                            sys.stderr.write(
                                "Warning: found several candidates for hg spec %s"
                                % spec)
                        break
                    self._do_pull()
                    repeated = True
            return None
        else:
            command = 'hg identify -i %s' % self._path
            _, output, _ = run_shell_command(command, shell=True, us_env=True)
            if output is None or output.strip() == '' or output.startswith(
                    "abort"):
                return None
            # hg adds a '+' to the end if there are uncommited
            # changes, inconsistent to hg log
            return output.strip().rstrip('+')
Example #37
0
 def update(self, version="", verbose=False, timeout=None):
     verboseflag = ""
     if verbose:
         verboseflag = "--verbose"
     if not self.detect_presence():
         sys.stderr.write("Error: cannot update non-existing directory\n")
         return True
     if not self._do_pull():
         return False
     if version is not None and version.strip() != "":
         cmd = "hg checkout %s %s" % (verboseflag, sanitized(version))
     else:
         cmd = "hg update %s --config ui.merge=internal:fail" % verboseflag
     value, _, _ = run_shell_command(cmd, cwd=self._path, shell=True, no_filter=True)
     if value != 0:
         return False
     return True
Example #38
0
 def get_status(self, basepath=None, untracked=False):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         # protect against shell injection
         command = "hg status %(path)s --repository %(path)s" % {"path": sanitized(rel_path)}
         if not untracked:
             command += " -mard"
         _, response, _ = run_shell_command(command, shell=True, cwd=basepath)
         if response is not None:
             if response.startswith("abort"):
                 raise VcsError("Probable Bug; Could not call %s, cwd=%s" % (command, basepath))
             if len(response) > 0 and response[-1] != "\n":
                 response += "\n"
     return response
 def get_status(self, basepath=None, untracked=False):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         command = "bzr status %s -S" % sanitized(rel_path)
         if not untracked:
             command += " -V"
         _, response, _ = run_shell_command(command, shell=True, cwd=basepath)
         response_processed = ""
         for line in response.split('\n'):
             if len(line.strip()) > 0:
                 response_processed += line[0:4] + rel_path + '/'
                 response_processed += line[4:] + '\n'
         response = response_processed
     return response
Example #40
0
 def get_status(self, basepath=None, untracked=False):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         command = "bzr status %s -S" % sanitized(rel_path)
         if not untracked:
             command += " -V"
         _, response, _ = run_shell_command(command, shell=True, cwd=basepath)
         response_processed = ""
         for line in response.split('\n'):
             if len(line.strip()) > 0:
                 response_processed += line[0:4] + rel_path + '/'
                 response_processed += line[4:] + '\n'
         response = response_processed
     return response
    def update(self, version=None, verbose=False):
        if not self.detect_presence():
            sys.stderr.write("Error: cannot update non-existing directory\n")
            return False
        # protect against shell injection

        if version is not None and version != '':
            if not version.startswith("-r"):
                version = "-r" + version
        elif version is None:
            version = ''
        cmd = 'svn up %s %s --non-interactive' % (sanitized(version),
                                                  self._path)
        value, _, _ = run_shell_command(cmd, shell=True, no_filter=True)
        if value == 0:
            return True
        return False
Example #42
0
 def get_status(self, basepath=None, untracked=False):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         # protect against shell injection
         command = 'svn status %s' % sanitized(rel_path)
         if not untracked:
             command += " -q"
         _, response, _ = run_shell_command(command,
                                            shell=True,
                                            cwd=basepath)
         if response is not None and \
            len(response) > 0 and \
            response[-1] != '\n':
             response += '\n'
     return response
 def get_status(self, basepath=None, untracked=False):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         # protect against shell injection
         command = 'svn status %s' % sanitized(rel_path)
         if not untracked:
             command += " -q"
         _, response, _ = run_shell_command(command,
                                            shell=True,
                                            cwd=basepath)
         if response is not None and \
            len(response) > 0 and \
            response[-1] != '\n':
             response += '\n'
     return response
Example #44
0
File: git.py Project: po1/vcstools
    def is_tag(self, tag_name, fetch=True):
        """
        checks list of tags for match.
        Set fetch to False if you just fetched already.

        :returns: True if tag_name among known tags
        :raises: GitError when call to git fetch fails
        """
        if fetch:
            self._do_fetch()
        if not tag_name:
            raise ValueError('is_tag requires tag_name, got: "%s"' % tag_name)
        if self.path_exists():
            cmd = 'git tag -l %s' % sanitized(tag_name)
            _, output, _ = run_shell_command(cmd, shell=True, cwd=self._path)
            lines = output.splitlines()
            if len(lines) == 1:
                return True
        return False
Example #45
0
    def is_tag(self, tag_name, fetch=True):
        """
        checks list of tags for match.
        Set fetch to False if you just fetched already.

        :returns: True if tag_name among known tags
        :raises: GitError when call to git fetch fails
        """
        if fetch:
            self._do_fetch()
        if not tag_name:
            raise ValueError('is_tag requires tag_name, got: "%s"' % tag_name)
        if self.path_exists():
            cmd = 'git tag -l %s' % sanitized(tag_name)
            _, output, _ = run_shell_command(cmd, shell=True, cwd=self._path)
            lines = output.splitlines()
            if len(lines) == 1:
                return True
        return False
Example #46
0
    def update(self, version=None, verbose=False):
        if not self.detect_presence():
            sys.stderr.write("Error: cannot update non-existing directory\n")
            return False
        # protect against shell injection

        if version is not None and version != '':
            if not version.startswith("-r"):
                version = "-r" + version
        elif version is None:
            version = ''
        cmd = 'svn up %s %s --non-interactive' % (sanitized(version),
                                                  self._path)
        value, _, _ = run_shell_command(cmd,
                                        shell=True,
                                        no_filter=True)
        if value == 0:
            return True
        return False
Example #47
0
    def get_log(self, relpath=None, limit=None):
        response = []

        if relpath is None:
            relpath = ''

        # Compile regexes
        id_regex = re.compile('^revno: ([0-9]+)$', flags=re.MULTILINE)
        committer_regex = re.compile('^committer: (.+)$', flags=re.MULTILINE)
        timestamp_regex = re.compile('^timestamp: (.+)$', flags=re.MULTILINE)
        message_regex = re.compile('^  (.+)$', flags=re.MULTILINE)

        if self.path_exists() and os.path.exists(
                os.path.join(self._path, relpath)):
            # Get the log
            limit_cmd = (("--limit=%d" % (int(limit))) if limit else "")
            command = "bzr log %s %s" % (sanitized(relpath), limit_cmd)
            return_code, text_response, stderr = run_shell_command(
                command, shell=True, cwd=self._path)
            if return_code == 0:
                revno_match = id_regex.findall(text_response)
                committer_match = committer_regex.findall(text_response)
                timestamp_match = timestamp_regex.findall(text_response)
                message_match = message_regex.findall(text_response)

                # Extract the entries
                for revno, committer, timestamp, message in zip(
                        revno_match, committer_match, timestamp_match,
                        message_match):
                    author, email_address = email.utils.parseaddr(committer)
                    date = dateutil.parser.parse(timestamp)
                    log_data = {
                        'id': revno,
                        'author': author,
                        'email': email_address,
                        'message': message,
                        'date': date
                    }

                    response.append(log_data)

        return response
Example #48
0
    def get_version(self, spec=None):
        """
        :param spec: (optional) token for identifying version. spec can be
          a whatever is allowed by 'hg log -r', e.g. a tagname, sha-ID,
          revision-number
        :returns: the current SHA-ID of the repository. Or if spec is
          provided, the SHA-ID of a revision specified by some
          token.
        """
        # detect presence only if we need path for cwd in popen
        if spec is not None:
            if self.detect_presence():
                command = 'hg log -r %s' % sanitized(spec)
                repeated = False
                output = ''
                # we repeat the call once after pullin if necessary
                while output == '':
                    _, output, _ = run_shell_command(command,
                                                     shell=True,
                                                     cwd=self._path,
                                                     us_env=True)
                    if (output.strip() != ''
                        and not output.startswith("abort")
                        or repeated is True):

                        matches = [l for l in output.splitlines() if l.startswith('changeset: ')]
                        if len(matches) == 1:
                            return matches[0].split(':')[2]
                        else:
                            sys.stderr.write("Warning: found several candidates for hg spec %s" % spec)
                        break
                    self._do_pull()
                    repeated = True
            return None
        else:
            command = 'hg identify -i %s' % self._path
            _, output, _ = run_shell_command(command, shell=True, us_env=True)
            if output is None or output.strip() == '' or output.startswith("abort"):
                return None
            # hg adds a '+' to the end if there are uncommited
            # changes, inconsistent to hg log
            return output.strip().rstrip('+')
Example #49
0
 def update(self, version='', verbose=False, timeout=None):
     verboseflag = ''
     if verbose:
         verboseflag = '--verbose'
     if not self.detect_presence():
         sys.stderr.write("Error: cannot update non-existing directory\n")
         return True
     if not self._do_pull():
         return False
     if version is not None and version.strip() != '':
         cmd = "hg checkout %s %s" % (verboseflag, sanitized(version))
     else:
         cmd = "hg update %s --config ui.merge=internal:fail" % verboseflag
     value, _, _ = run_shell_command(cmd,
                                     cwd=self._path,
                                     shell=True,
                                     no_filter=True)
     if value != 0:
         return False
     return True
Example #50
0
 def get_status(self, basepath=None, untracked=False):
     response = None
     if basepath is None:
         basepath = self._path
     if self.path_exists():
         rel_path = normalized_rel_path(self._path, basepath)
         # protect against shell injection
         command = "hg status %(path)s --repository %(path)s" % {
             'path': sanitized(rel_path)
         }
         if not untracked:
             command += " -mard"
         _, response, _ = run_shell_command(command,
                                            shell=True,
                                            cwd=basepath)
         if response is not None:
             if response.startswith("abort"):
                 raise VcsError("Probable Bug; Could not call %s, cwd=%s" %
                                (command, basepath))
             if len(response) > 0 and response[-1] != '\n':
                 response += '\n'
     return response
Example #51
0
    def test_sanitized(self):
        self.assertEqual('', sanitized(None))
        self.assertEqual('', sanitized(''))
        self.assertEqual('"foo"', sanitized('foo'))
        self.assertEqual('"foo"', sanitized('\"foo\"'))
        self.assertEqual('"foo"', sanitized('"foo"'))
        self.assertEqual('"foo"', sanitized('" foo"'))

        try:
            sanitized('bla"; foo"')
            self.fail("Expected Exception")
        except VcsError:
            pass
        try:
            sanitized('bla";foo"')
            self.fail("Expected Exception")
        except VcsError:
            pass
        try:
            sanitized('bla";foo \"bum')
            self.fail("Expected Exception")
        except VcsError:
            pass
        try:
            sanitized('bla";foo;"bam')
            self.fail("Expected Exception")
        except VcsError:
            pass
        try:
            sanitized('bla"#;foo;"bam')
            self.fail("Expected Exception")
        except VcsError:
            pass
Example #52
0
    def test_sanitized(self):
        self.assertEqual('', sanitized(None))
        self.assertEqual('', sanitized(''))
        self.assertEqual('"foo"', sanitized('foo'))
        self.assertEqual('"foo"', sanitized('\"foo\"'))
        self.assertEqual('"foo"', sanitized('"foo"'))
        self.assertEqual('"foo"', sanitized('" foo"'))

        try:
            sanitized('bla"; foo"')
            self.fail("Expected Exception")
        except VcsError:
            pass
        try:
            sanitized('bla";foo"')
            self.fail("Expected Exception")
        except VcsError:
            pass
        try:
            sanitized('bla";foo \"bum')
            self.fail("Expected Exception")
        except VcsError:
            pass
        try:
            sanitized('bla";foo;"bam')
            self.fail("Expected Exception")
        except VcsError:
            pass
        try:
            sanitized('bla"#;foo;"bam')
            self.fail("Expected Exception")
        except VcsError:
            pass