Example #1
0
    def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
        p1 = self._getpath(path_parts1)
        p2 = self._getpath(path_parts2)
        r1 = self._getrev(rev1)
        r2 = self._getrev(rev2)
        if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
            raise vclib.ItemNotFound(path_parts1)
        if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
            raise vclib.ItemNotFound(path_parts2)

        args = vclib._diff_args(type, options)

        def _date_from_rev(rev):
            date, author, msg, revprops, changes = self._revinfo(rev)
            return date

        try:
            temp1 = cat_to_tempfile(self, p1, r1)
            temp2 = cat_to_tempfile(self, p2, r2)
            info1 = p1, _date_from_rev(r1), r1
            info2 = p2, _date_from_rev(r2), r2
            return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd,
                                  args)
        except core.SubversionException, e:
            _fix_subversion_exception(e)
            if e.apr_err == vclib.svn.core.SVN_ERR_FS_NOT_FOUND:
                raise vclib.InvalidRevision
            raise
Example #2
0
 def _simple_auth_check(fsroot):
     """Return a 2-tuple: found_readable, found_unreadable."""
     found_unreadable = found_readable = 0
     if hasattr(fs, "paths_changed2"):
         changes = fs.paths_changed2(fsroot)
     else:
         changes = fs.paths_changed(fsroot)
     paths = list(changes.keys())
     for path in paths:
         change = changes[path]
         pathtype = None
         if hasattr(change, "node_kind"):
             if change.node_kind == core.svn_node_file:
                 pathtype = vclib.FILE
             elif change.node_kind == core.svn_node_dir:
                 pathtype = vclib.DIR
         parts = _path_parts(path)
         if pathtype is None:
             # Figure out the pathtype so we can query the authz subsystem.
             if change.change_kind == fs.path_change_delete:
                 # Deletions are annoying, because they might be underneath
                 # copies (make their previous location non-trivial).
                 prev_parts = parts
                 prev_rev = rev - 1
                 parent_parts = parts[:-1]
                 while parent_parts:
                     parent_path = "/" + self._getpath(parent_parts)
                     pchange = changes.get(parent_path)
                     if not (
                         pchange
                         and (
                             pchange.change_kind == fs.path_change_replace
                             or pchange.change_kind == fs.path_change_add
                         )
                     ):
                         del parent_parts[-1]
                         continue
                     copyfrom_path, copyfrom_rev = _get_change_copyinfo(
                         fsroot, parent_path, pchange
                     )
                     if copyfrom_path:
                         prev_rev = copyfrom_rev
                         prev_parts = _path_parts(copyfrom_path) + parts[len(parent_parts) :]
                         break
                     del parent_parts[-1]
                 pathtype = self._gettype(self._getpath(prev_parts), prev_rev)
             else:
                 pathtype = self._gettype(self._getpath(parts), rev)
         if vclib.check_path_access(self, parts, pathtype, rev):
             found_readable = 1
             copyfrom_path, copyfrom_rev = _get_change_copyinfo(fsroot, path, change)
             if copyfrom_path and copyfrom_path != path:
                 parts = _path_parts(copyfrom_path)
                 if not vclib.check_path_access(self, parts, pathtype, copyfrom_rev):
                     found_unreadable = 1
         else:
             found_unreadable = 1
         if found_readable and found_unreadable:
             break
     return found_readable, found_unreadable
  def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
    p1 = self._getpath(path_parts1)
    p2 = self._getpath(path_parts2)
    r1 = self._getrev(rev1)
    r2 = self._getrev(rev2)
    if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
      raise vclib.ItemNotFound(path_parts1)
    if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
      raise vclib.ItemNotFound(path_parts2)

    args = vclib._diff_args(type, options)

    def _date_from_rev(rev):
      date, author, msg, changes = self.revinfo(rev)
      return date
    
    try:
      temp1 = temp_checkout(self, p1, r1)
      temp2 = temp_checkout(self, p2, r2)
      info1 = p1, _date_from_rev(r1), r1
      info2 = p2, _date_from_rev(r2), r2
      return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd, args)
    except core.SubversionException, e:
      _fix_subversion_exception(e)
      if e.apr_err == vclib.svn.core.SVN_ERR_FS_NOT_FOUND:
        raise vclib.InvalidRevision
      raise
Example #4
0
        def _get_changed_paths(fsroot):
            """Return a 3-tuple: found_readable, found_unreadable, changed_paths."""
            editor = repos.ChangeCollector(self.fs_ptr, fsroot)
            e_ptr, e_baton = delta.make_editor(editor)
            repos.svn_repos_replay(fsroot, e_ptr, e_baton)
            changedpaths = {}
            changes = editor.get_changes()

            # Copy the Subversion changes into a new hash, checking
            # authorization and converting them into ChangedPath objects.
            found_readable = found_unreadable = 0
            for path in changes.keys():
                spath = _to_str(path)
                change = changes[path]
                if change.path:
                    change.path = _cleanup_path(change.path)
                if change.base_path:
                    change.base_path = _cleanup_path(change.base_path)
                is_copy = 0
                action = {
                    repos.CHANGE_ACTION_ADD: vclib.ADDED,
                    repos.CHANGE_ACTION_DELETE: vclib.DELETED,
                    repos.CHANGE_ACTION_REPLACE: vclib.REPLACED,
                }.get(change.action, vclib.MODIFIED)
                if ((action == vclib.ADDED or action == vclib.REPLACED)
                        and change.base_path and change.base_rev):
                    is_copy = 1
                pathtype = _kind2type(change.item_kind)
                parts = _path_parts(spath)
                if vclib.check_path_access(self, parts, pathtype, rev):
                    if is_copy and change.base_path and (change.base_path !=
                                                         path):
                        parts = _path_parts(_to_str(change.base_path))
                        if not vclib.check_path_access(self, parts, pathtype,
                                                       change.base_rev):
                            is_copy = 0
                            change.base_path = None
                            change.base_rev = None
                            found_unreadable = 1
                    if change.base_path:
                        base_path = _to_str(change.base_path)
                    else:
                        base_path = None
                    changedpaths[spath] = SVNChangedPath(
                        spath,
                        rev,
                        pathtype,
                        base_path,
                        change.base_rev,
                        action,
                        is_copy,
                        change.text_changed,
                        change.prop_changes,
                    )
                    found_readable = 1
                else:
                    found_unreadable = 1
            return found_readable, found_unreadable, list(
                changedpaths.values())
Example #5
0
 def _simple_auth_check(fsroot):
   """Return a 2-tuple: found_readable, found_unreadable."""
   found_unreadable = found_readable = 0
   if hasattr(fs, 'paths_changed2'):
     changes = fs.paths_changed2(fsroot)
   else:
     changes = fs.paths_changed(fsroot)
   paths = changes.keys()
   for path in paths:
     change = changes[path]
     pathtype = None
     if hasattr(change, 'node_kind'):
       if change.node_kind == core.svn_node_file:
         pathtype = vclib.FILE
       elif change.node_kind == core.svn_node_dir:
         pathtype = vclib.DIR
     parts = _path_parts(path)
     if pathtype is None:
       # Figure out the pathtype so we can query the authz subsystem.
       if change.change_kind == fs.path_change_delete:
         # Deletions are annoying, because they might be underneath
         # copies (make their previous location non-trivial).
         prev_parts = parts
         prev_rev = rev - 1
         parent_parts = parts[:-1]
         while parent_parts:
           parent_path = '/' + self._getpath(parent_parts)
           parent_change = changes.get(parent_path)
           if not (parent_change and \
                   (parent_change.change_kind == fs.path_change_add or
                    parent_change.change_kind == fs.path_change_replace)):
             del(parent_parts[-1])
             continue
           copyfrom_path, copyfrom_rev = \
             _get_change_copyinfo(fsroot, parent_path, parent_change)
           if copyfrom_path:
             prev_rev = copyfrom_rev
             prev_parts = _path_parts(copyfrom_path) + \
                          parts[len(parent_parts):]
             break
           del(parent_parts[-1])
         pathtype = self._gettype(self._getpath(prev_parts), prev_rev)
       else:
         pathtype = self._gettype(self._getpath(parts), rev)
     if vclib.check_path_access(self, parts, pathtype, rev):
       found_readable = 1
       copyfrom_path, copyfrom_rev = \
         _get_change_copyinfo(fsroot, path, change)
       if copyfrom_path and copyfrom_path != path:
         parts = _path_parts(copyfrom_path)
         if not vclib.check_path_access(self, parts, pathtype,
                                        copyfrom_rev):
           found_unreadable = 1
     else:
       found_unreadable = 1
     if found_readable and found_unreadable:
       break
   return found_readable, found_unreadable
    def _log_cb(changed_paths, revision, author,
                datestr, message, pool, retval=revs):
      date = _datestr_to_date(datestr)
      action_map = { 'D' : vclib.DELETED,
                     'A' : vclib.ADDED,
                     'R' : vclib.REPLACED,
                     'M' : vclib.MODIFIED,
                     }
      paths = (changed_paths or {}).keys()
      paths.sort(lambda a, b: _compare_paths(a, b))
      changes = []
      found_readable = found_unreadable = 0
      for path in paths:
        pathtype = None
        change = changed_paths[path]
        action = action_map.get(change.action, vclib.MODIFIED)
        ### Wrong, diddily wrong wrong wrong.  Can you say,
        ### "Manufacturing data left and right because it hurts to
        ### figure out the right stuff?"
        if change.copyfrom_path and change.copyfrom_rev:
          is_copy = 1
          base_path = change.copyfrom_path
          base_rev = change.copyfrom_rev
        elif action == vclib.ADDED or action == vclib.REPLACED:
          is_copy = 0
          base_path = base_rev = None
        else:
          is_copy = 0
          base_path = path
          base_rev = revision - 1

        ### Check authz rules (we lie about the path type)
        parts = _path_parts(path)
        if vclib.check_path_access(self, parts, vclib.FILE, revision):
          if is_copy and base_path and (base_path != path):
            parts = _path_parts(base_path)
            if vclib.check_path_access(self, parts, vclib.FILE, base_rev):
              is_copy = 0
              base_path = None
              base_rev = None
          changes.append(SVNChangedPath(path, revision, pathtype, base_path,
                                        base_rev, action, is_copy, 0, 0))
          found_readable = 1
        else:
          found_unreadable = 1

      if found_unreadable:
        message = None
        if not found_readable:
          author = None
          date = None
      revs.append([date, author, message, changes])
Example #7
0
  def _get_dirents(self, path, rev):
    """Return a 2-type of dirents and locks, possibly reading/writing
    from a local cache of that information.  This functions performs
    authz checks, stripping out unreadable dirents."""

    dir_url = self._geturl(path)
    path_parts = _path_parts(path)    
    if path:
      key = str(rev) + '/' + path
    else:
      key = str(rev)

    # Ensure that the cache gets filled...
    dirents_locks = self._dirent_cache.get(key)
    if not dirents_locks:
      tmp_dirents, locks = list_directory(dir_url, _rev2optrev(rev),
                                          _rev2optrev(rev), 0, self.ctx)
      dirents = {}
      for name, dirent in tmp_dirents.items():
        dirent_parts = path_parts + [name]
        kind = dirent.kind 
        if (kind == core.svn_node_dir or kind == core.svn_node_file) \
           and vclib.check_path_access(self, dirent_parts,
                                       kind == core.svn_node_dir \
                                         and vclib.DIR or vclib.FILE, rev):
          lh_rev, c_rev = self._get_last_history_rev(dirent_parts, rev)
          dirent.created_rev = lh_rev
          dirents[name] = dirent
      dirents_locks = [dirents, locks]
      self._dirent_cache[key] = dirents_locks

    # ...then return the goodies from the cache.
    return dirents_locks[0], dirents_locks[1]
Example #8
0
  def dirlogs(self, path_parts, rev, entries, options):
    """see vclib.Repository.dirlogs docstring

    rev can be a tag name or None. if set only information from revisions
    matching the tag will be retrieved

    Option values recognized by this implementation:

      cvs_subdirs
        boolean. true to fetch logs of the most recently modified file in each
        subdirectory

    Option values returned by this implementation:

      cvs_tags, cvs_branches
        lists of tag and branch names encountered in the directory
    """
    if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
      raise vclib.Error("Path '%s' is not a directory."
                        % (_path_join(path_parts)))

    subdirs = options.get('cvs_subdirs', 0)
    entries_to_fetch = []
    for entry in entries:
      if vclib.check_path_access(self, path_parts + [entry.name], None, rev):
        entries_to_fetch.append(entry)
    alltags = _get_logs(self, path_parts, entries_to_fetch, rev, subdirs)
    branches = options['cvs_branches'] = []
    tags = options['cvs_tags'] = []
    for name, rev in alltags.items():
      if Tag(None, rev).is_branch:
        branches.append(name)
      else:
        tags.append(name)
Example #9
0
    def _get_history(self, path, rev, path_type, limit=0, options={}):
        if self.youngest == 0:
            return []

        rev_paths = []
        fsroot = self._getroot(rev)
        show_all_logs = options.get("svn_show_all_dir_logs", 0)
        if not show_all_logs:
            # See if the path is a file or directory.
            kind = fs.check_path(fsroot, path)
            if kind is core.svn_node_file:
                show_all_logs = 1

        # Instantiate a NodeHistory collector object, and use it to collect
        # history items for PATH@REV.
        history = NodeHistory(self.fs_ptr, show_all_logs, limit)
        try:
            repos.svn_repos_history(self.fs_ptr, path, history.add_history, 1,
                                    rev, options.get("svn_cross_copies", 0))
        except core.SubversionException as e:
            if e.apr_err != core.SVN_ERR_CEASE_INVOCATION:
                raise

        # Now, iterate over those history items, checking for changes of
        # location, pruning as necessitated by authz rules.
        for hist_rev, hist_path in history:
            hist_path = _to_str(hist_path)
            path_parts = _path_parts(hist_path)
            if not vclib.check_path_access(self, path_parts, path_type,
                                           hist_rev):
                break
            rev_paths.append([hist_rev, hist_path])
        return rev_paths
Example #10
0
  def dirlogs(self, path_parts, rev, entries, options):
    """see vclib.Repository.dirlogs docstring

    rev can be a tag name or None. if set only information from revisions
    matching the tag will be retrieved

    Option values recognized by this implementation:

      cvs_subdirs
        boolean. true to fetch logs of the most recently modified file in each
        subdirectory

    Option values returned by this implementation:

      cvs_tags, cvs_branches
        lists of tag and branch names encountered in the directory
    """
    if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
      raise vclib.Error("Path '%s' is not a directory."
                        % (_path_join(path_parts)))

    subdirs = options.get('cvs_subdirs', 0)
    entries_to_fetch = []
    for entry in entries:
      if vclib.check_path_access(self, path_parts + [entry.name], None, rev):
        entries_to_fetch.append(entry)
    alltags = _get_logs(self, path_parts, entries_to_fetch, rev, subdirs)
    branches = options['cvs_branches'] = []
    tags = options['cvs_tags'] = []
    for name, rev in alltags.items():
      if Tag(None, rev).is_branch:
        branches.append(name)
      else:
        tags.append(name)
Example #11
0
    def _get_dirents(self, path, rev):
        """Return a 2-type of dirents and locks, possibly reading/writing
    from a local cache of that information.  This functions performs
    authz checks, stripping out unreadable dirents."""

        dir_url = self._geturl(path)
        path_parts = _path_parts(path)
        if path:
            key = str(rev) + '/' + path
        else:
            key = str(rev)

        # Ensure that the cache gets filled...
        dirents_locks = self._dirent_cache.get(key)
        if not dirents_locks:
            tmp_dirents, locks = list_directory(dir_url, _rev2optrev(rev),
                                                _rev2optrev(rev), 0, self.ctx)
            dirents = {}
            for name, dirent in tmp_dirents.items():
                dirent_parts = path_parts + [name]
                kind = dirent.kind
                if (kind == core.svn_node_dir or kind == core.svn_node_file) \
                   and vclib.check_path_access(self, dirent_parts,
                                               kind == core.svn_node_dir \
                                                 and vclib.DIR or vclib.FILE, rev):
                    lh_rev, c_rev = self._get_last_history_rev(
                        dirent_parts, rev)
                    dirent.created_rev = lh_rev
                    dirents[name] = dirent
            dirents_locks = [dirents, locks]
            self._dirent_cache[key] = dirents_locks

        # ...then return the goodies from the cache.
        return dirents_locks[0], dirents_locks[1]
Example #12
0
    def dirlogs(self, path_parts, rev, entries, options):
        """see vclib.Repository.dirlogs docstring

    rev can be a tag name or None. if set only information from revisions
    matching the tag will be retrieved

    Option values recognized by this implementation:

      cvs_subdirs
        boolean. true to fetch logs of the most recently modified file in each
        subdirectory

    Option values returned by this implementation:

      cvs_tags, cvs_branches
        lists of tag and branch names encountered in the directory
    """
        if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
            raise vclib.Error("Path '%s' is not a directory." %
                              (part2path(path_parts)))
        entries_to_fetch = []
        for entry in entries:
            if vclib.check_path_access(self, path_parts + [entry.name], None,
                                       rev):
                entries_to_fetch.append(entry)

        subdirs = options.get('cvs_subdirs', 0)

        dirpath = self._getpath(path_parts)
        alltags = {  # all the tags seen in the files of this dir
            'MAIN': '',
            'HEAD': '1.1'
        }

        for entry in entries_to_fetch:
            entry.rev = entry.date = entry.author = None
            entry.dead = entry.absent = entry.log = entry.lockinfo = None
            path = _log_path(entry, dirpath, subdirs)
            if path:
                entry.path = path
                try:
                    rcsparse.parse(
                        open(path, 'rb'),
                        InfoSink(entry, rev, alltags, self.encoding))
                except IOError as e:
                    entry.errors.append("rcsparse error: %s" % e)
                except RuntimeError as e:
                    entry.errors.append("rcsparse error: %s" % e)
                except rcsparse.RCSStopParser:
                    pass

        branches = options['cvs_branches'] = []
        tags = options['cvs_tags'] = []
        for name, rev in alltags.items():
            if Tag(None, rev).is_branch:
                branches.append(name)
            else:
                tags.append(name)
Example #13
0
  def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
    if path_parts1:
      p1 = self._getpath(path_parts1)
      r1 = self._getrev(rev1)
      if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
        raise vclib.ItemNotFound(path_parts1)
    else:
      p1 = None

    if path_parts2:
      p2 = self._getpath(path_parts2)
      r2 = self._getrev(rev2)
      if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
        raise vclib.ItemNotFound(path_parts2)
    else:
      if not p1:
        raise vclib.ItemNotFound(path_parts2)
      p2 = None

    args = vclib._diff_args(type, options)

    def _date_from_rev(rev):
      date, author, msg, revprops, changes = self._revinfo(rev)
      return date

    try:
      if p1:
        temp1 = temp_checkout(self, p1, r1)
        info1 = p1, _date_from_rev(r1), r1
      else:
        temp1 = '/dev/null'
        info1 = '/dev/null', _date_from_rev(rev1), rev1
      if p2:
        temp2 = temp_checkout(self, p2, r2)
        info2 = p2, _date_from_rev(r2), r2
      else:
        temp2 = '/dev/null'
        info2 = '/dev/null', _date_from_rev(rev2), rev2
      return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd, args)
    except core.SubversionException, e:
      _fix_subversion_exception(e)
      if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
        raise vclib.InvalidRevision
      if e.apr_err != _SVN_ERR_CEASE_INVOCATION:
        raise
Example #14
0
 def itemtype(self, path_parts, rev):
   rev = self._getrev(rev)
   basepath = self._getpath(path_parts)
   pathtype = self._gettype(basepath, rev)
   if pathtype is None:
     raise vclib.ItemNotFound(path_parts)
   if not vclib.check_path_access(self, path_parts, pathtype, rev):
     raise vclib.ItemNotFound(path_parts)
   return pathtype
Example #15
0
 def itemtype(self, path_parts, rev):
     rev = self._getrev(rev)
     basepath = self._getpath(path_parts)
     pathtype = self._gettype(basepath, rev)
     if pathtype is None:
         raise vclib.ItemNotFound(path_parts)
     if not vclib.check_path_access(self, path_parts, pathtype, rev):
         raise vclib.ItemNotFound(path_parts)
     return pathtype
Example #16
0
    def listdir(self, path_parts, rev, options):
        if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
            raise vclib.Error("Path '%s' is not a directory." %
                              (_path_join(path_parts)))

        # Only RCS files (*,v) and subdirs are returned.
        data = []
        full_name = self._getpath(path_parts)
        for file in os.listdir(full_name):
            name = None
            kind, errors = _check_path(os.path.join(full_name, file))
            if kind == vclib.FILE:
                if file[-2:] == ',v':
                    name = file[:-2]
            elif kind == vclib.DIR:
                if file != 'Attic' and file != 'CVS':  # CVS directory is for fileattr
                    name = file
            else:
                name = file
            if not name:
                continue
            if vclib.check_path_access(self, path_parts + [name], kind, rev):
                data.append(CVSDirEntry(name, kind, errors, 0))

        full_name = os.path.join(full_name, 'Attic')
        if os.path.isdir(full_name):
            for file in os.listdir(full_name):
                name = None
                kind, errors = _check_path(os.path.join(full_name, file))
                if kind == vclib.FILE:
                    if file[-2:] == ',v':
                        name = file[:-2]
                elif kind != vclib.DIR:
                    name = file
                if not name:
                    continue
                if vclib.check_path_access(self, path_parts + [name], kind,
                                           rev):
                    data.append(CVSDirEntry(name, kind, errors, 1))

        return data
Example #17
0
  def listdir(self, path_parts, rev, options):
    if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
      raise vclib.Error("Path '%s' is not a directory."
                        % (_path_join(path_parts)))
    
    # Only RCS files (*,v) and subdirs are returned.
    data = [ ]
    full_name = self._getpath(path_parts)
    for file in os.listdir(full_name):
      name = None
      kind, errors = _check_path(os.path.join(full_name, file))
      if kind == vclib.FILE:
        if file[-2:] == ',v':
          name = file[:-2]
      elif kind == vclib.DIR:
        if file != 'Attic' and file != 'CVS': # CVS directory is for fileattr
          name = file
      else:
        name = file
      if not name:
        continue
      if vclib.check_path_access(self, path_parts + [name], kind, rev):
        data.append(CVSDirEntry(name, kind, errors, 0))

    full_name = os.path.join(full_name, 'Attic')
    if os.path.isdir(full_name):
      for file in os.listdir(full_name):
        name = None
        kind, errors = _check_path(os.path.join(full_name, file))
        if kind == vclib.FILE:
          if file[-2:] == ',v':
            name = file[:-2]
        elif kind != vclib.DIR:
          name = file
        if not name:
          continue
        if vclib.check_path_access(self, path_parts + [name], kind, rev):
          data.append(CVSDirEntry(name, kind, errors, 1))

    return data
Example #18
0
  def dirlogs(self, path_parts, rev, entries, options):
    """see vclib.Repository.dirlogs docstring

    rev can be a tag name or None. if set only information from revisions
    matching the tag will be retrieved

    Option values recognized by this implementation:

      cvs_subdirs
        boolean. true to fetch logs of the most recently modified file in each
        subdirectory

    Option values returned by this implementation:

      cvs_tags, cvs_branches
        lists of tag and branch names encountered in the directory
    """
    if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
      raise vclib.Error("Path '%s' is not a directory."
                        % (part2path(path_parts)))
    entries_to_fetch = []
    for entry in entries:
      if vclib.check_path_access(self, path_parts + [entry.name], None, rev):
        entries_to_fetch.append(entry)

    subdirs = options.get('cvs_subdirs', 0)

    dirpath = self._getpath(path_parts)
    alltags = {           # all the tags seen in the files of this dir
      'MAIN' : '',
      'HEAD' : '1.1'
    }

    for entry in entries_to_fetch:
      entry.rev = entry.date = entry.author = None
      entry.dead = entry.absent = entry.log = entry.lockinfo = None
      path = _log_path(entry, dirpath, subdirs)
      if path:
        entry.path = path
        try:
          rcsparse.parse(open(path, 'rb'), InfoSink(entry, rev, alltags))
          if self.guesser:
            entry.log = self.guesser.utf8(entry.log)
        except IOError, e:
          entry.errors.append("rcsparse error: %s" % e)
        except RuntimeError, e:
          entry.errors.append("rcsparse error: %s" % e)
        except rcsparse.RCSStopParser:
          pass
Example #19
0
 def listdir(self, path_parts, rev, options):
     path = self._getpath(path_parts)
     if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
         raise vclib.Error("Path '%s' is not a directory." % path)
     rev = self._getrev(rev)
     fsroot = self._getroot(rev)
     dirents = fs.dir_entries(fsroot, path)
     entries = []
     for entry in dirents.values():
         kind = _kind2type(entry.kind)
         ent_path = _to_str(entry.name)
         if vclib.check_path_access(self, path_parts + [ent_path], kind,
                                    rev):
             entries.append(vclib.DirEntry(ent_path, kind))
     return entries
Example #20
0
 def itemtype(self, path_parts, rev):
   basepath = self._getpath(path_parts)
   kind = None
   if os.path.isdir(basepath):
     kind = vclib.DIR
   elif os.path.isfile(basepath + ',v'):
     kind = vclib.FILE
   else:
     atticpath = self._getpath(self._atticpath(path_parts))
     if os.path.isfile(atticpath + ',v'):
       kind = vclib.FILE
   if not kind:
     raise vclib.ItemNotFound(path_parts)
   if not vclib.check_path_access(self, path_parts, kind, rev):
     raise vclib.ItemNotFound(path_parts)
   return kind
Example #21
0
 def listdir(self, path_parts, rev, options):
     path = self._getpath(path_parts)
     if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
         raise vclib.Error("Path '%s' is not a directory." % path)
     rev = self._getrev(rev)
     entries = []
     dirents, locks = self._get_dirents(path, rev)
     for name in dirents.keys():
         entry = dirents[name]
         if entry.kind == core.svn_node_dir:
             kind = vclib.DIR
         elif entry.kind == core.svn_node_file:
             kind = vclib.FILE
         if vclib.check_path_access(self, path_parts + [name], kind, rev):
             entries.append(vclib.DirEntry(name, kind))
     return entries
Example #22
0
 def listdir(self, path_parts, rev, options):
   path = self._getpath(path_parts)
   if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
     raise vclib.Error("Path '%s' is not a directory." % path)
   rev = self._getrev(rev)
   fsroot = self._getroot(rev)
   dirents = fs.dir_entries(fsroot, path)
   entries = [ ]
   for entry in dirents.values():
     if entry.kind == core.svn_node_dir:
       kind = vclib.DIR
     elif entry.kind == core.svn_node_file:
       kind = vclib.FILE
     if vclib.check_path_access(self, path_parts + [entry.name], kind, rev):
       entries.append(vclib.DirEntry(entry.name, kind))
   return entries
Example #23
0
 def itemtype(self, path_parts, rev):
   basepath = self._getpath(path_parts)
   kind = None
   if os.path.isdir(basepath):
     kind = vclib.DIR
   elif os.path.isfile(basepath + ',v'):
     kind = vclib.FILE
   else:
     atticpath = self._getpath(self._atticpath(path_parts))
     if os.path.isfile(atticpath + ',v'):
       kind = vclib.FILE
   if not kind:
     raise vclib.ItemNotFound(path_parts)
   if not vclib.check_path_access(self, path_parts, kind, rev):
     raise vclib.ItemNotFound(path_parts)
   return kind
Example #24
0
 def listdir(self, path_parts, rev, options):
   path = self._getpath(path_parts)
   if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
     raise vclib.Error("Path '%s' is not a directory." % path)
   rev = self._getrev(rev)
   fsroot = self._getroot(rev)
   dirents = fs.dir_entries(fsroot, path)
   entries = [ ]
   for entry in dirents.values():
     if entry.kind == core.svn_node_dir:
       kind = vclib.DIR
     elif entry.kind == core.svn_node_file:
       kind = vclib.FILE
     if vclib.check_path_access(self, path_parts + [entry.name], kind, rev):
       entries.append(vclib.DirEntry(entry.name, kind))
   return entries
 def listdir(self, path_parts, rev, options):
   path = self._getpath(path_parts)
   if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
     raise vclib.Error("Path '%s' is not a directory." % path)
   rev = self._getrev(rev)
   entries = [ ]
   dirents, locks = self._get_dirents(path, rev)
   for name in dirents.keys():
     entry = dirents[name]
     if entry.kind == core.svn_node_dir:
       kind = vclib.DIR
     elif entry.kind == core.svn_node_file:
       kind = vclib.FILE
     if vclib.check_path_access(self, path_parts + [name], kind, rev):
       entries.append(vclib.DirEntry(name, kind))
   return entries
Example #26
0
 def get_location(self, path, rev, old_rev):
   try:
     results = ra.get_locations(self.ra_session, path, rev, [old_rev])
   except core.SubversionException as e:
     if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
       raise vclib.ItemNotFound(path)
     raise
   try:
     old_path = results[old_rev]
   except KeyError:
     raise vclib.ItemNotFound(path)
   old_path = _cleanup_path(_to_str(old_path))
   old_path_parts = _path_parts(old_path)
   # Check access (lying about path types)
   if not vclib.check_path_access(self, old_path_parts, vclib.FILE, old_rev):
     raise vclib.ItemNotFound(path)
   return old_path
Example #27
0
 def itemtype(self, path_parts, rev):
     pathtype = None
     if not len(path_parts):
         pathtype = vclib.DIR
     else:
         path = self._getpath(path_parts)
         rev = self._getrev(rev)
         try:
             kind = ra.svn_ra_check_path(self.ra_session, path, rev)
             pathtype = _kind2type(kind)
         except Exception:
             pass
     if pathtype is None:
         raise vclib.ItemNotFound(path_parts)
     if not vclib.check_path_access(self, path_parts, pathtype, rev):
         raise vclib.ItemNotFound(path_parts)
     return pathtype
 def dirlogs(self, path_parts, rev, entries, options):
   path = self._getpath(path_parts)
   if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
     raise vclib.Error("Path '%s' is not a directory." % path)
   rev = self._getrev(rev)
   dirents, locks = self._get_dirents(path, rev)
   for entry in entries:
     entry_path_parts = path_parts + [entry.name]
     if not vclib.check_path_access(self, entry_path_parts, entry.kind, rev):
       continue
     dirent = dirents[entry.name]
     entry.date, entry.author, entry.log, changes = \
                 self.revinfo(dirent.created_rev)
     entry.rev = str(dirent.created_rev)
     entry.size = dirent.size
     entry.lockinfo = None
     if locks.has_key(entry.name):
       entry.lockinfo = locks[entry.name].owner
Example #29
0
 def dirlogs(self, path_parts, rev, entries, options):
     path = self._getpath(path_parts)
     if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
         raise vclib.Error("Path '%s' is not a directory." % path)
     rev = self._getrev(rev)
     dirents, locks = self._get_dirents(path, rev)
     for entry in entries:
         entry_path_parts = path_parts + [entry.name]
         if not vclib.check_path_access(self, entry_path_parts, entry.kind,
                                        rev):
             continue
         dirent = dirents[entry.name]
         entry.date, entry.author, entry.log, revprops, changes = \
                     self.revinfo(dirent.created_rev)
         entry.rev = str(dirent.created_rev)
         entry.size = dirent.size
         entry.lockinfo = None
         if locks.has_key(entry.name):
             entry.lockinfo = locks[entry.name].owner
 def itemtype(self, path_parts, rev):
   pathtype = None
   if not len(path_parts):
     pathtype = vclib.DIR
   else:
     path = self._getpath(path_parts)
     rev = self._getrev(rev)
     try:
       kind = ra.svn_ra_check_path(self.ra_session, path, rev)
       if kind == core.svn_node_file:
         pathtype = vclib.FILE
       elif kind == core.svn_node_dir:
         pathtype = vclib.DIR
     except:
       pass
   if pathtype is None:
     raise vclib.ItemNotFound(path_parts)
   if not vclib.check_path_access(self, path_parts, pathtype, rev):
     raise vclib.ItemNotFound(path_parts)
   return pathtype
Example #31
0
 def itemtype(self, path_parts, rev):
     pathtype = None
     if not len(path_parts):
         pathtype = vclib.DIR
     else:
         path = self._getpath(path_parts)
         rev = self._getrev(rev)
         try:
             kind = ra.svn_ra_check_path(self.ra_session, path, rev)
             if kind == core.svn_node_file:
                 pathtype = vclib.FILE
             elif kind == core.svn_node_dir:
                 pathtype = vclib.DIR
         except:
             pass
     if pathtype is None:
         raise vclib.ItemNotFound(path_parts)
     if not vclib.check_path_access(self, path_parts, pathtype, rev):
         raise vclib.ItemNotFound(path_parts)
     return pathtype
Example #32
0
 def dirlogs(self, path_parts, rev, entries, options):
   path = self._getpath(path_parts)
   if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
     raise vclib.Error("Path '%s' is not a directory." % path)
   fsroot = self._getroot(self._getrev(rev))
   rev = self._getrev(rev)
   for entry in entries:
     entry_path_parts = path_parts + [entry.name]
     if not vclib.check_path_access(self, entry_path_parts, entry.kind, rev):
       continue
     path = self._getpath(entry_path_parts)
     entry_rev = _get_last_history_rev(fsroot, path)
     date, author, msg, revprops, changes = self._revinfo(entry_rev)
     entry.rev = str(entry_rev)
     entry.date = date
     entry.author = author
     entry.log = msg
     if entry.kind == vclib.FILE:
       entry.size = fs.file_length(fsroot, path)
     lock = fs.get_lock(self.fs_ptr, path)
     entry.lockinfo = lock and lock.owner or None
Example #33
0
 def dirlogs(self, path_parts, rev, entries, options):
   path = self._getpath(path_parts)
   if self.itemtype(path_parts, rev) != vclib.DIR:  # does auth-check
     raise vclib.Error("Path '%s' is not a directory." % path)
   fsroot = self._getroot(self._getrev(rev))
   rev = self._getrev(rev)
   for entry in entries:
     entry_path_parts = path_parts + [entry.name]
     if not vclib.check_path_access(self, entry_path_parts, entry.kind, rev):
       continue
     path = self._getpath(entry_path_parts)
     entry_rev = _get_last_history_rev(fsroot, path)
     date, author, msg, revprops, changes = self._revinfo(entry_rev)
     entry.rev = str(entry_rev)
     entry.date = date
     entry.author = author
     entry.log = msg
     if entry.kind == vclib.FILE:
       entry.size = fs.file_length(fsroot, path)
     lock = fs.get_lock(self.fs_ptr, path)
     entry.lockinfo = lock and lock.owner or None
Example #34
0
        def _log_cb(log_entry, pool, retval=revs):
            # If Subversion happens to call us more than once, we choose not
            # to care.
            if retval:
                return

            revision = log_entry.revision
            msg, author, date, revprops = _split_revprops(log_entry.revprops)
            action_map = {
                'D': vclib.DELETED,
                'A': vclib.ADDED,
                'R': vclib.REPLACED,
                'M': vclib.MODIFIED,
            }

            # Easy out: if we won't use the changed-path info, just return a
            # changes-less tuple.
            if not need_changes:
                return revs.append([date, author, msg, revprops, None])

            # Subversion 1.5 and earlier didn't offer the 'changed_paths2'
            # hash, and in Subversion 1.6, it's offered but broken.
            try:
                changed_paths = log_entry.changed_paths2
                paths = (changed_paths or {}).keys()
            except:
                changed_paths = log_entry.changed_paths
                paths = (changed_paths or {}).keys()
            paths.sort(lambda a, b: _compare_paths(a, b))

            # If we get this far, our caller needs changed-paths, or we need
            # them for authz-related sanitization.
            changes = []
            found_readable = found_unreadable = 0
            for path in paths:
                change = changed_paths[path]

                # svn_log_changed_path_t (which we might get instead of the
                # svn_log_changed_path2_t we'd prefer) doesn't have the
                # 'node_kind' member.
                pathtype = None
                if hasattr(change, 'node_kind'):
                    if change.node_kind == core.svn_node_dir:
                        pathtype = vclib.DIR
                    elif change.node_kind == core.svn_node_file:
                        pathtype = vclib.FILE

                # svn_log_changed_path2_t only has the 'text_modified' and
                # 'props_modified' bits in Subversion 1.7 and beyond.  And
                # svn_log_changed_path_t is without.
                text_modified = props_modified = 0
                if hasattr(change, 'text_modified'):
                    if change.text_modified == core.svn_tristate_true:
                        text_modified = 1
                if hasattr(change, 'props_modified'):
                    if change.props_modified == core.svn_tristate_true:
                        props_modified = 1

                # Wrong, diddily wrong wrong wrong.  Can you say,
                # "Manufacturing data left and right because it hurts to
                # figure out the right stuff?"
                action = action_map.get(change.action, vclib.MODIFIED)
                if change.copyfrom_path and change.copyfrom_rev:
                    is_copy = 1
                    base_path = change.copyfrom_path
                    base_rev = change.copyfrom_rev
                elif action == vclib.ADDED or action == vclib.REPLACED:
                    is_copy = 0
                    base_path = base_rev = None
                else:
                    is_copy = 0
                    base_path = path
                    base_rev = revision - 1

                # Check authz rules (sadly, we have to lie about the path type)
                parts = _path_parts(path)
                if vclib.check_path_access(self, parts, vclib.FILE, revision):
                    if is_copy and base_path and (base_path != path):
                        parts = _path_parts(base_path)
                        if not vclib.check_path_access(self, parts, vclib.FILE,
                                                       base_rev):
                            is_copy = 0
                            base_path = None
                            base_rev = None
                            found_unreadable = 1
                    changes.append(
                        SVNChangedPath(path, revision, pathtype, base_path,
                                       base_rev, action, is_copy,
                                       text_modified, props_modified))
                    found_readable = 1
                else:
                    found_unreadable = 1

                # If our caller doesn't want changed-path stuff, and we have
                # the info we need to make an authz determination already,
                # quit this loop and get on with it.
                if (not include_changed_paths
                    ) and found_unreadable and found_readable:
                    break

            # Filter unreadable information.
            if found_unreadable:
                msg = None
                if not found_readable:
                    author = None
                    date = None

            # Drop unrequested changes.
            if not include_changed_paths:
                changes = None

            # Add this revision information to the "return" array.
            retval.append([date, author, msg, revprops, changes])
Example #35
0
        def _log_cb(log_entry, pool, retval=revs):
            ### Subversion 1.5 and earlier didn't offer the 'changed_paths2'
            ### hash, and in Subversion 1.6, it's offered but broken.
            try:
                changed_paths = log_entry.changed_paths2
                paths = (changed_paths or {}).keys()
            except:
                changed_paths = log_entry.changed_paths
                paths = (changed_paths or {}).keys()
            paths.sort(lambda a, b: _compare_paths(a, b))
            revision = log_entry.revision
            msg, author, date, revprops = _split_revprops(log_entry.revprops)
            action_map = {
                'D': vclib.DELETED,
                'A': vclib.ADDED,
                'R': vclib.REPLACED,
                'M': vclib.MODIFIED,
            }
            changes = []
            found_readable = found_unreadable = 0
            for path in paths:
                change = changed_paths[path]
                ### svn_log_changed_path_t (which we might get instead of the
                ### svn_log_changed_path2_t we'd prefer) doesn't have the
                ### 'node_kind' member.
                pathtype = None
                if hasattr(change, 'node_kind'):
                    if change.node_kind == core.svn_node_dir:
                        pathtype = vclib.DIR
                    elif change.node_kind == core.svn_node_file:
                        pathtype = vclib.FILE
                ### svn_log_changed_path2_t only has the 'text_modified' and
                ### 'props_modified' bits in Subversion 1.7 and beyond.  And
                ### svn_log_changed_path_t is without.
                text_modified = props_modified = 0
                if hasattr(change, 'text_modified'):
                    if change.text_modified == core.svn_tristate_true:
                        text_modified = 1
                if hasattr(change, 'props_modified'):
                    if change.props_modified == core.svn_tristate_true:
                        props_modified = 1
                ### Wrong, diddily wrong wrong wrong.  Can you say,
                ### "Manufacturing data left and right because it hurts to
                ### figure out the right stuff?"
                action = action_map.get(change.action, vclib.MODIFIED)
                if change.copyfrom_path and change.copyfrom_rev:
                    is_copy = 1
                    base_path = change.copyfrom_path
                    base_rev = change.copyfrom_rev
                elif action == vclib.ADDED or action == vclib.REPLACED:
                    is_copy = 0
                    base_path = base_rev = None
                else:
                    is_copy = 0
                    base_path = path
                    base_rev = revision - 1

                ### Check authz rules (we lie about the path type)
                parts = _path_parts(path)
                if vclib.check_path_access(self, parts, vclib.FILE, revision):
                    if is_copy and base_path and (base_path != path):
                        parts = _path_parts(base_path)
                        if vclib.check_path_access(self, parts, vclib.FILE,
                                                   base_rev):
                            is_copy = 0
                            base_path = None
                            base_rev = None
                    changes.append(
                        SVNChangedPath(path, revision, pathtype, base_path,
                                       base_rev, action, is_copy,
                                       text_modified, props_modified))
                    found_readable = 1
                else:
                    found_unreadable = 1

            if found_unreadable:
                msg = None
                if not found_readable:
                    author = None
                    date = None
            revs.append([date, author, msg, revprops, changes])
Example #36
0
 def _access_checker(check_path, check_rev):
     return vclib.check_path_access(self, _path_parts(check_path),
                                    path_type, check_rev)
Example #37
0
        def _get_changed_paths(fsroot):
            """Return a 3-tuple: found_readable, found_unreadable, changed_paths."""
            editor = repos.ChangeCollector(self.fs_ptr, fsroot)
            e_ptr, e_baton = delta.make_editor(editor)
            repos.svn_repos_replay(fsroot, e_ptr, e_baton)
            changedpaths = {}
            changes = editor.get_changes()

            # Copy the Subversion changes into a new hash, checking
            # authorization and converting them into ChangedPath objects.
            found_readable = found_unreadable = 0
            for path in changes.keys():
                change = changes[path]
                if change.path:
                    change.path = _cleanup_path(change.path)
                if change.base_path:
                    change.base_path = _cleanup_path(change.base_path)
                is_copy = 0
                if not hasattr(change, 'action'):  # new to subversion 1.4.0
                    action = vclib.MODIFIED
                    if not change.path:
                        action = vclib.DELETED
                    elif change.added:
                        action = vclib.ADDED
                        replace_check_path = path
                        if change.base_path and change.base_rev:
                            replace_check_path = change.base_path
                        if changedpaths.has_key(replace_check_path) \
                           and changedpaths[replace_check_path].action == vclib.DELETED:
                            action = vclib.REPLACED
                else:
                    if change.action == repos.CHANGE_ACTION_ADD:
                        action = vclib.ADDED
                    elif change.action == repos.CHANGE_ACTION_DELETE:
                        action = vclib.DELETED
                    elif change.action == repos.CHANGE_ACTION_REPLACE:
                        action = vclib.REPLACED
                    else:
                        action = vclib.MODIFIED
                if (action == vclib.ADDED or action == vclib.REPLACED) \
                   and change.base_path \
                   and change.base_rev:
                    is_copy = 1
                if change.item_kind == core.svn_node_dir:
                    pathtype = vclib.DIR
                elif change.item_kind == core.svn_node_file:
                    pathtype = vclib.FILE
                else:
                    pathtype = None

                parts = _path_parts(path)
                if vclib.check_path_access(self, parts, pathtype, rev):
                    if is_copy and change.base_path and (change.base_path !=
                                                         path):
                        parts = _path_parts(change.base_path)
                        if not vclib.check_path_access(self, parts, pathtype,
                                                       change.base_rev):
                            is_copy = 0
                            change.base_path = None
                            change.base_rev = None
                            found_unreadable = 1
                    changedpaths[path] = SVNChangedPath(
                        path, rev, pathtype, change.base_path, change.base_rev,
                        action, is_copy, change.text_changed,
                        change.prop_changes)
                    found_readable = 1
                else:
                    found_unreadable = 1
            return found_readable, found_unreadable, changedpaths.values()
Example #38
0
  def get_location(self, path, rev, old_rev):
    try:
      results = ra.get_locations(self.ra_session, path, rev, [old_rev])
    except core.SubversionException, e:
      _fix_subversion_exception(e)
      if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
        raise vclib.ItemNotFound(path)
      raise
    try:
      old_path = results[old_rev]
    except KeyError:
      raise vclib.ItemNotFound(path)
    old_path = _cleanup_path(old_path)
    old_path_parts = _path_parts(old_path)
    # Check access (lying about path types)
    if not vclib.check_path_access(self, old_path_parts, vclib.FILE, old_rev):
      raise vclib.ItemNotFound(path)
    return old_path
  
  def created_rev(self, path, rev):
    lh_rev, c_rev = self._get_last_history_rev(_path_parts(path), rev)
    return lh_rev

  def last_rev(self, path, peg_revision, limit_revision=None):
    """Given PATH, known to exist in PEG_REVISION, find the youngest
    revision older than, or equal to, LIMIT_REVISION in which path
    exists.  Return that revision, and the path at which PATH exists in
    that revision."""
    
    # Here's the plan, man.  In the trivial case (where PEG_REVISION is
    # the same as LIMIT_REVISION), this is a no-brainer.  If
Example #39
0
 def _access_checker(check_path, check_rev):
   return vclib.check_path_access(self, _path_parts(check_path),
                                  path_type, check_rev)
Example #40
0
        def _log_cb(log_entry, pool, retval=revs):
            # If Subversion happens to call us more than once, we choose not
            # to care.
            if retval:
                return

            revision = log_entry.revision
            msg, author, date, revprops = _split_revprops(log_entry.revprops)
            action_map = {
                "D": vclib.DELETED,
                "A": vclib.ADDED,
                "R": vclib.REPLACED,
                "M": vclib.MODIFIED,
            }

            # Easy out: if we won't use the changed-path info, just return a
            # changes-less tuple.
            if not need_changes:
                return revs.append([date, author, msg, revprops, None])

            # Subversion 1.5 and earlier didn't offer the 'changed_paths2'
            # hash, and in Subversion 1.6, it's offered but broken.
            try:
                changed_paths = log_entry.changed_paths2
                paths = list((changed_paths or {}).keys())
            except Exception:
                changed_paths = log_entry.changed_paths
                paths = list((changed_paths or {}).keys())
            paths.sort(key=functools.cmp_to_key(
                lambda a, b: _compare_paths(_to_str(a), _to_str(b))))

            # If we get this far, our caller needs changed-paths, or we need
            # them for authz-related sanitization.
            changes = []
            found_readable = found_unreadable = 0
            for path in paths:
                change = changed_paths[path]
                pathtype = _kind2type(change.node_kind)
                text_modified = (change.text_modified == core.svn_tristate_true
                                 and 1 or 0)
                props_modified = (
                    change.props_modified == core.svn_tristate_true and 1 or 0)

                # Wrong, diddily wrong wrong wrong.  Can you say,
                # "Manufacturing data left and right because it hurts to
                # figure out the right stuff?"
                action = action_map.get(change.action, vclib.MODIFIED)
                if change.copyfrom_path and change.copyfrom_rev:
                    is_copy = 1
                    base_path = change.copyfrom_path
                    base_rev = change.copyfrom_rev
                elif action == vclib.ADDED or action == vclib.REPLACED:
                    is_copy = 0
                    base_path = base_rev = None
                else:
                    is_copy = 0
                    base_path = path
                    base_rev = revision - 1

                # Check authz rules (sadly, we have to lie about the path type)
                parts = _path_parts(_to_str(path))
                if vclib.check_path_access(self, parts, vclib.FILE, revision):
                    if is_copy and base_path and (base_path != path):
                        parts = _path_parts(_to_str(base_path))
                        if not vclib.check_path_access(self, parts, vclib.FILE,
                                                       base_rev):
                            is_copy = 0
                            base_path = None
                            base_rev = None
                            found_unreadable = 1
                    changes.append(
                        SVNChangedPath(
                            _to_str(path),
                            revision,
                            pathtype,
                            _to_str(base_path),
                            base_rev,
                            action,
                            is_copy,
                            text_modified,
                            props_modified,
                        ))
                    found_readable = 1
                else:
                    found_unreadable = 1

                # If our caller doesn't want changed-path stuff, and we have
                # the info we need to make an authz determination already,
                # quit this loop and get on with it.
                if (not include_changed_paths
                    ) and found_unreadable and found_readable:
                    break

            # Filter unreadable information.
            if found_unreadable:
                msg = None
                if not found_readable:
                    author = None
                    date = None

            # Drop unrequested changes.
            if not include_changed_paths:
                changes = None

            # Add this revision information to the "return" array.
            retval.append([date, author, msg, revprops, changes])
Example #41
0
    # Instantiate a NodeHistory collector object, and use it to collect
    # history items for PATH@REV.
    history = NodeHistory(self.fs_ptr, show_all_logs, limit)
    try:
      repos.svn_repos_history(self.fs_ptr, path, history.add_history,
                              1, rev, options.get('svn_cross_copies', 0))
    except core.SubversionException, e:
      _fix_subversion_exception(e)
      if e.apr_err != _SVN_ERR_CEASE_INVOCATION:
        raise

    # Now, iterate over those history items, checking for changes of
    # location, pruning as necessitated by authz rules.
    for hist_rev, hist_path in history:
      path_parts = _path_parts(hist_path)
      if not vclib.check_path_access(self, path_parts, path_type, hist_rev):
        break
      rev_paths.append([hist_rev, hist_path])
    return rev_paths
  
  def _getpath(self, path_parts):
    return '/'.join(path_parts)

  def _getrev(self, rev):
    if rev is None or rev == 'HEAD':
      return self.youngest
    try:
      if type(rev) == type(''):
        while rev[0] == 'r':
          rev = rev[1:]
      rev = int(rev)
Example #42
0
   def _get_changed_paths(fsroot):
     """Return a 3-tuple: found_readable, found_unreadable, changed_paths."""
     editor = repos.ChangeCollector(self.fs_ptr, fsroot)
     e_ptr, e_baton = delta.make_editor(editor)
     repos.svn_repos_replay(fsroot, e_ptr, e_baton)
     changedpaths = {}
     changes = editor.get_changes()
   
     # Copy the Subversion changes into a new hash, checking
     # authorization and converting them into ChangedPath objects.
     found_readable = found_unreadable = 0
     for path in changes.keys():
       change = changes[path]
       if change.path:
         change.path = _cleanup_path(change.path)
       if change.base_path:
         change.base_path = _cleanup_path(change.base_path)
       is_copy = 0
       if not hasattr(change, 'action'): # new to subversion 1.4.0
         action = vclib.MODIFIED
         if not change.path:
           action = vclib.DELETED
         elif change.added:
           action = vclib.ADDED
           replace_check_path = path
           if change.base_path and change.base_rev:
             replace_check_path = change.base_path
           if changedpaths.has_key(replace_check_path) \
              and changedpaths[replace_check_path].action == vclib.DELETED:
             action = vclib.REPLACED
       else:
         if change.action == repos.CHANGE_ACTION_ADD:
           action = vclib.ADDED
         elif change.action == repos.CHANGE_ACTION_DELETE:
           action = vclib.DELETED
         elif change.action == repos.CHANGE_ACTION_REPLACE:
           action = vclib.REPLACED
         else:
           action = vclib.MODIFIED
       if (action == vclib.ADDED or action == vclib.REPLACED) \
          and change.base_path \
          and change.base_rev:
         is_copy = 1
       if change.item_kind == core.svn_node_dir:
         pathtype = vclib.DIR
       elif change.item_kind == core.svn_node_file:
         pathtype = vclib.FILE
       else:
         pathtype = None
 
       parts = _path_parts(path)
       if vclib.check_path_access(self, parts, pathtype, rev):
         if is_copy and change.base_path and (change.base_path != path):
           parts = _path_parts(change.base_path)
           if not vclib.check_path_access(self, parts, pathtype,
                                          change.base_rev):
             is_copy = 0
             change.base_path = None
             change.base_rev = None
             found_unreadable = 1
         changedpaths[path] = SVNChangedPath(path, rev, pathtype,
                                             change.base_path,
                                             change.base_rev, action,
                                             is_copy, change.text_changed,
                                             change.prop_changes)
         found_readable = 1
       else:
         found_unreadable = 1
     return found_readable, found_unreadable, changedpaths.values()
Example #43
0
    def _log_cb(log_entry, pool, retval=revs):
      # If Subversion happens to call us more than once, we choose not
      # to care.
      if retval:
        return
      
      revision = log_entry.revision
      msg, author, date, revprops = _split_revprops(log_entry.revprops)
      action_map = { 'D' : vclib.DELETED,
                     'A' : vclib.ADDED,
                     'R' : vclib.REPLACED,
                     'M' : vclib.MODIFIED,
                     }

      # Easy out: if we won't use the changed-path info, just return a
      # changes-less tuple.
      if not need_changes:
        return revs.append([date, author, msg, revprops, None])

      # Subversion 1.5 and earlier didn't offer the 'changed_paths2'
      # hash, and in Subversion 1.6, it's offered but broken.
      try: 
        changed_paths = log_entry.changed_paths2
        paths = (changed_paths or {}).keys()
      except:
        changed_paths = log_entry.changed_paths
        paths = (changed_paths or {}).keys()
      paths.sort(lambda a, b: _compare_paths(a, b))

      # If we get this far, our caller needs changed-paths, or we need
      # them for authz-related sanitization.
      changes = []
      found_readable = found_unreadable = 0
      for path in paths:
        change = changed_paths[path]

        # svn_log_changed_path_t (which we might get instead of the
        # svn_log_changed_path2_t we'd prefer) doesn't have the
        # 'node_kind' member.        
        pathtype = None
        if hasattr(change, 'node_kind'):
          if change.node_kind == core.svn_node_dir:
            pathtype = vclib.DIR
          elif change.node_kind == core.svn_node_file:
            pathtype = vclib.FILE
            
        # svn_log_changed_path2_t only has the 'text_modified' and
        # 'props_modified' bits in Subversion 1.7 and beyond.  And
        # svn_log_changed_path_t is without.
        text_modified = props_modified = 0
        if hasattr(change, 'text_modified'):
          if change.text_modified == core.svn_tristate_true:
            text_modified = 1
        if hasattr(change, 'props_modified'):
          if change.props_modified == core.svn_tristate_true:
            props_modified = 1
            
        # Wrong, diddily wrong wrong wrong.  Can you say,
        # "Manufacturing data left and right because it hurts to
        # figure out the right stuff?"
        action = action_map.get(change.action, vclib.MODIFIED)
        if change.copyfrom_path and change.copyfrom_rev:
          is_copy = 1
          base_path = change.copyfrom_path
          base_rev = change.copyfrom_rev
        elif action == vclib.ADDED or action == vclib.REPLACED:
          is_copy = 0
          base_path = base_rev = None
        else:
          is_copy = 0
          base_path = path
          base_rev = revision - 1

        # Check authz rules (sadly, we have to lie about the path type)
        parts = _path_parts(path)
        if vclib.check_path_access(self, parts, vclib.FILE, revision):
          if is_copy and base_path and (base_path != path):
            parts = _path_parts(base_path)
            if not vclib.check_path_access(self, parts, vclib.FILE, base_rev):
              is_copy = 0
              base_path = None
              base_rev = None
              found_unreadable = 1
          changes.append(SVNChangedPath(path, revision, pathtype, base_path,
                                        base_rev, action, is_copy,
                                        text_modified, props_modified))
          found_readable = 1
        else:
          found_unreadable = 1

        # If our caller doesn't want changed-path stuff, and we have
        # the info we need to make an authz determination already,
        # quit this loop and get on with it.
        if (not include_changed_paths) and found_unreadable and found_readable:
          break

      # Filter unreadable information.
      if found_unreadable:
        msg = None
        if not found_readable:
          author = None
          date = None

      # Drop unrequested changes.
      if not include_changed_paths:
        changes = None

      # Add this revision information to the "return" array.
      retval.append([date, author, msg, revprops, changes])
Example #44
0
    def get_location(self, path, rev, old_rev):
        try:
            results = ra.get_locations(self.ra_session, path, rev, [old_rev])
        except core.SubversionException, e:
            _fix_subversion_exception(e)
            if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
                raise vclib.ItemNotFound(path)
            raise
        try:
            old_path = results[old_rev]
        except KeyError:
            raise vclib.ItemNotFound(path)
        old_path = _cleanup_path(old_path)
        old_path_parts = _path_parts(old_path)
        # Check access (lying about path types)
        if not vclib.check_path_access(self, old_path_parts, vclib.FILE,
                                       old_rev):
            raise vclib.ItemNotFound(path)
        return old_path

    def created_rev(self, path, rev):
        lh_rev, c_rev = self._get_last_history_rev(_path_parts(path), rev)
        return lh_rev

    def last_rev(self, path, peg_revision, limit_revision=None):
        """Given PATH, known to exist in PEG_REVISION, find the youngest
    revision older than, or equal to, LIMIT_REVISION in which path
    exists.  Return that revision, and the path at which PATH exists in
    that revision."""

        # Here's the plan, man.  In the trivial case (where PEG_REVISION is
        # the same as LIMIT_REVISION), this is a no-brainer.  If
Example #45
0
    def itemlog(self, path_parts, rev, sortby, first, limit, options):
        """see vclib.Repository.itemlog docstring

        Option values recognized by this implementation

          svn_show_all_dir_logs
            boolean, default false. if set for a directory path, will include
            revisions where files underneath the directory have changed

          svn_cross_copies
            boolean, default false. if set for a path created by a copy, will
            include revisions from before the copy

          svn_latest_log
            boolean, default false. if set will return only newest single log
            entry
        """
        assert sortby == vclib.SORTBY_DEFAULT or sortby == vclib.SORTBY_REV

        path = self._getpath(path_parts)
        path_type = self.itemtype(path_parts, rev)  # does auth-check
        rev = self._getrev(rev)
        revs = []
        lockinfo = None

        # See if this path is locked.
        try:
            lock = fs.get_lock(self.fs_ptr, path)
            if lock:
                lockinfo = _to_str(lock.owner)
        except NameError:
            pass

        # If our caller only wants the latest log, we'll invoke
        # _log_helper for just the one revision.  Otherwise, we go off
        # into history-fetching mode.  ### TODO: we could stand to have a
        # 'limit' parameter here as numeric cut-off for the depth of our
        # history search.
        if options.get("svn_latest_log", 0):
            revision = self._log_helper(path, rev, lockinfo)
            if revision:
                revision.prev = None
                revs.append(revision)
        else:
            history = self._get_history(path, rev, path_type, first + limit,
                                        options)
            if len(history) < first:
                history = []
            if limit:
                history = history[first:(first + limit)]

            for hist_rev, hist_path in history:
                revision = self._log_helper(hist_path, hist_rev, lockinfo)
                if revision:
                    # If we have unreadable copyfrom data, obscure it.
                    if revision.copy_path is not None:
                        cp_parts = _path_parts(revision.copy_path)
                        if not vclib.check_path_access(
                                self, cp_parts, path_type, revision.copy_rev):
                            revision.copy_path = revision.copy_rev = None
                    revision.prev = None
                    if len(revs):
                        revs[-1].prev = revision
                    revs.append(revision)
        return revs
Example #46
0
        # Instantiate a NodeHistory collector object, and use it to collect
        # history items for PATH@REV.
        history = NodeHistory(self.fs_ptr, show_all_logs, limit)
        try:
            repos.svn_repos_history(self.fs_ptr, path, history.add_history, 1,
                                    rev, options.get('svn_cross_copies', 0))
        except core.SubversionException, e:
            _fix_subversion_exception(e)
            if e.apr_err != _SVN_ERR_CEASE_INVOCATION:
                raise

        # Now, iterate over those history items, checking for changes of
        # location, pruning as necessitated by authz rules.
        for hist_rev, hist_path in history:
            path_parts = _path_parts(hist_path)
            if not vclib.check_path_access(self, path_parts, path_type,
                                           hist_rev):
                break
            rev_paths.append([hist_rev, hist_path])
        return rev_paths

    def _getpath(self, path_parts):
        return '/'.join(path_parts)

    def _getrev(self, rev):
        if rev is None or rev == 'HEAD':
            return self.youngest
        try:
            if type(rev) == type(''):
                while rev[0] == 'r':
                    rev = rev[1:]
            rev = int(rev)
Example #47
0
    def _log_cb(log_entry, pool, retval=revs):
      ### Subversion 1.5 and earlier didn't offer the 'changed_paths2'
      ### hash, and in Subversion 1.6, it's offered but broken.
      try: 
        changed_paths = log_entry.changed_paths2
        paths = (changed_paths or {}).keys()
      except:
        changed_paths = log_entry.changed_paths
        paths = (changed_paths or {}).keys()
      paths.sort(lambda a, b: _compare_paths(a, b))
      revision = log_entry.revision
      msg, author, date, revprops = _split_revprops(log_entry.revprops)
      action_map = { 'D' : vclib.DELETED,
                     'A' : vclib.ADDED,
                     'R' : vclib.REPLACED,
                     'M' : vclib.MODIFIED,
                     }
      changes = []
      found_readable = found_unreadable = 0
      for path in paths:
        change = changed_paths[path]
        ### svn_log_changed_path_t (which we might get instead of the
        ### svn_log_changed_path2_t we'd prefer) doesn't have the
        ### 'node_kind' member.        
        pathtype = None
        if hasattr(change, 'node_kind'):
          if change.node_kind == core.svn_node_dir:
            pathtype = vclib.DIR
          elif change.node_kind == core.svn_node_file:
            pathtype = vclib.FILE
        ### svn_log_changed_path2_t only has the 'text_modified' and
        ### 'props_modified' bits in Subversion 1.7 and beyond.  And
        ### svn_log_changed_path_t is without.
        text_modified = props_modified = 0
        if hasattr(change, 'text_modified'):
          if change.text_modified == core.svn_tristate_true:
            text_modified = 1
        if hasattr(change, 'props_modified'):
          if change.props_modified == core.svn_tristate_true:
            props_modified = 1
        ### Wrong, diddily wrong wrong wrong.  Can you say,
        ### "Manufacturing data left and right because it hurts to
        ### figure out the right stuff?"
        action = action_map.get(change.action, vclib.MODIFIED)
        if change.copyfrom_path and change.copyfrom_rev:
          is_copy = 1
          base_path = change.copyfrom_path
          base_rev = change.copyfrom_rev
        elif action == vclib.ADDED or action == vclib.REPLACED:
          is_copy = 0
          base_path = base_rev = None
        else:
          is_copy = 0
          base_path = path
          base_rev = revision - 1

        ### Check authz rules (we lie about the path type)
        parts = _path_parts(path)
        if vclib.check_path_access(self, parts, vclib.FILE, revision):
          if is_copy and base_path and (base_path != path):
            parts = _path_parts(base_path)
            if vclib.check_path_access(self, parts, vclib.FILE, base_rev):
              is_copy = 0
              base_path = None
              base_rev = None
          changes.append(SVNChangedPath(path, revision, pathtype, base_path,
                                        base_rev, action, is_copy,
                                        text_modified, props_modified))
          found_readable = 1
        else:
          found_unreadable = 1

      if found_unreadable:
        msg = None
        if not found_readable:
          author = None
          date = None
      revs.append([date, author, msg, revprops, changes])
Example #48
0
  def itemlog(self, path_parts, rev, sortby, first, limit, options):
    """see vclib.Repository.itemlog docstring

    Option values recognized by this implementation

      svn_show_all_dir_logs
        boolean, default false. if set for a directory path, will include
        revisions where files underneath the directory have changed

      svn_cross_copies
        boolean, default false. if set for a path created by a copy, will
        include revisions from before the copy

      svn_latest_log
        boolean, default false. if set will return only newest single log
        entry
    """
    assert sortby == vclib.SORTBY_DEFAULT or sortby == vclib.SORTBY_REV   

    path = self._getpath(path_parts)
    path_type = self.itemtype(path_parts, rev)  # does auth-check
    rev = self._getrev(rev)
    revs = []
    lockinfo = None

    # See if this path is locked.
    try:
      lock = fs.get_lock(self.fs_ptr, path)
      if lock:
        lockinfo = lock.owner
    except NameError:
      pass

    # If our caller only wants the latest log, we'll invoke
    # _log_helper for just the one revision.  Otherwise, we go off
    # into history-fetching mode.  ### TODO: we could stand to have a
    # 'limit' parameter here as numeric cut-off for the depth of our
    # history search.
    if options.get('svn_latest_log', 0):
      revision = self._log_helper(path, rev, lockinfo)
      if revision:
        revision.prev = None
        revs.append(revision)
    else:
      history = self._get_history(path, rev, path_type, first + limit, options)
      if len(history) < first:
        history = []
      if limit:
        history = history[first:first+limit]

      for hist_rev, hist_path in history:
        revision = self._log_helper(hist_path, hist_rev, lockinfo)
        if revision:
          # If we have unreadable copyfrom data, obscure it.
          if revision.copy_path is not None:
            cp_parts = _path_parts(revision.copy_path)
            if not vclib.check_path_access(self, cp_parts, path_type,
                                           revision.copy_rev):
              revision.copy_path = revision.copy_rev = None
          revision.prev = None
          if len(revs):
            revs[-1].prev = revision
          revs.append(revision)
    return revs