Example #1
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 #2
0
 def itemprops(self, path_parts, rev):
     path = self._getpath(path_parts)
     path_type = self.itemtype(path_parts, rev)  # does auth-check
     rev = self._getrev(rev)
     url = self._geturl(path)
     pairs = client.svn_client_proplist2(url, _rev2optrev(rev), _rev2optrev(rev), 0, self.ctx)
     return pairs and pairs[0][1] or {}
Example #3
0
    def _get_last_history_rev(self, path_parts, rev):
        """Return the a 2-tuple which contains:
         - the last interesting revision equal to or older than REV in
           the history of PATH_PARTS.
         - the created_rev of of PATH_PARTS as of REV."""

        path = self._getpath(path_parts)
        url = self._geturl(self._getpath(path_parts))
        optrev = _rev2optrev(rev)

        # Get the last-changed-rev.
        revisions = []

        def _info_cb(path, info, pool, retval=revisions):
            revisions.append(info.last_changed_rev)

        client.svn_client_info(url, optrev, optrev, _info_cb, 0, self.ctx)
        last_changed_rev = revisions[0]

        # Now, this object might not have been directly edited since the
        # last-changed-rev, but it might have been the child of a copy.
        # To determine this, we'll run a potentially no-op log between
        # LAST_CHANGED_REV and REV.
        lc = LogCollector(path, 1, None, None)
        client_log(url, optrev, _rev2optrev(last_changed_rev), 1, 1, 0,
                   lc.add_log, self.ctx)
        revs = lc.logs
        if revs:
            revs.sort()
            return revs[0].number, last_changed_rev
        else:
            return last_changed_rev, last_changed_rev
Example #4
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 #5
0
    def annotate(self, path_parts, rev):
        path = self._getpath(path_parts)
        if self.itemtype(path_parts, rev) != vclib.FILE:  # does auth-check
            raise vclib.Error("Path '%s' is not a file." % path)
        rev = self._getrev(rev)
        url = self._geturl(path)

        blame_data = []

        def _blame_cb(line_no,
                      revision,
                      author,
                      date,
                      line,
                      pool,
                      blame_data=blame_data):
            prev_rev = None
            if revision > 1:
                prev_rev = revision - 1
            blame_data.append(
                vclib.Annotation(line, line_no + 1, revision, prev_rev, author,
                                 None))

        client.svn_client_blame(url, _rev2optrev(1), _rev2optrev(rev),
                                _blame_cb, self.ctx)

        return blame_data, rev
Example #6
0
    def get_symlink_target(self, path_parts, rev):
        """Return the target of the symbolic link versioned at PATH_PARTS
    in REV, or None if that object is not a symlink."""

        path = self._getpath(path_parts)
        path_type = self.itemtype(path_parts, rev)  # does auth-check
        rev = self._getrev(rev)
        url = self._geturl(path)

        # Symlinks must be files with the svn:special property set on them
        # and with file contents which read "link SOME_PATH".
        if path_type != vclib.FILE:
            return None
        pairs = client.svn_client_proplist2(url, _rev2optrev(rev),
                                            _rev2optrev(rev), 0, self.ctx)
        props = pairs and pairs[0][1] or {}
        if not props.has_key(core.SVN_PROP_SPECIAL):
            return None
        pathspec = ''
        ### FIXME: We're being a touch sloppy here, first by grabbing the
        ### whole file and then by checking only the first line
        ### of it.
        fp = SelfCleanFP(cat_to_tempfile(self, path, rev))
        pathspec = fp.readline()
        fp.close()
        if pathspec[:5] != 'link ':
            return None
        return pathspec[5:]
Example #7
0
  def _get_last_history_rev(self, path_parts, rev):
    """Return the a 2-tuple which contains:
         - the last interesting revision equal to or older than REV in
           the history of PATH_PARTS.
         - the created_rev of of PATH_PARTS as of REV."""
    
    path = self._getpath(path_parts)
    url = self._geturl(self._getpath(path_parts))
    optrev = _rev2optrev(rev)

    # Get the last-changed-rev.
    revisions = []
    def _info_cb(path, info, pool, retval=revisions):
      revisions.append(info.last_changed_rev)
    client.svn_client_info(url, optrev, optrev, _info_cb, 0, self.ctx)
    last_changed_rev = revisions[0]

    # Now, this object might not have been directly edited since the
    # last-changed-rev, but it might have been the child of a copy.
    # To determine this, we'll run a potentially no-op log between
    # LAST_CHANGED_REV and REV.
    lc = LogCollector(path, 1, None, None)
    client_log(url, optrev, _rev2optrev(last_changed_rev), 1, 1, 0,
               lc.add_log, self.ctx)
    revs = lc.logs
    if revs:
      revs.sort()
      return revs[0].number, last_changed_rev
    else:
      return last_changed_rev, last_changed_rev
Example #8
0
  def get_symlink_target(self, path_parts, rev):
    """Return the target of the symbolic link versioned at PATH_PARTS
    in REV, or None if that object is not a symlink."""

    path = self._getpath(path_parts)
    path_type = self.itemtype(path_parts, rev) # does auth-check
    rev = self._getrev(rev)
    url = self._geturl(path)

    # Symlinks must be files with the svn:special property set on them
    # and with file contents which read "link SOME_PATH".
    if path_type != vclib.FILE:
      return None
    pairs = client.svn_client_proplist2(url, _rev2optrev(rev),
                                        _rev2optrev(rev), 0, self.ctx)
    props = pairs and pairs[0][1] or {}
    if not props.has_key(core.SVN_PROP_SPECIAL):
      return None
    pathspec = ''
    ### FIXME: We're being a touch sloppy here, first by grabbing the
    ### whole file and then by checking only the first line
    ### of it.
    fp = SelfCleanFP(cat_to_tempfile(self, path, rev))
    pathspec = fp.readline()
    fp.close()
    if pathspec[:5] != 'link ':
      return None
    return pathspec[5:]
Example #9
0
 def itemprops(self, path_parts, rev):
     path = self._getpath(path_parts)
     path_type = self.itemtype(path_parts, rev)  # does auth-check
     rev = self._getrev(rev)
     url = self._geturl(path)
     pairs = client.svn_client_proplist2(url, _rev2optrev(rev),
                                         _rev2optrev(rev), 0, self.ctx)
     return pairs and pairs[0][1] or {}
Example #10
0
    def itemlog(self, path_parts, rev, sortby, first, limit, options):
        assert sortby == vclib.SORTBY_DEFAULT or sortby == vclib.SORTBY_REV
        path_type = self.itemtype(path_parts, rev)  # does auth-check
        path = self._getpath(path_parts)
        rev = self._getrev(rev)
        url = self._geturl(path)

        # If this is a file, fetch the lock status and size (as of REV)
        # for this item.
        lockinfo = size_in_rev = None
        if path_type == vclib.FILE:
            basename = path_parts[-1]
            list_url = self._geturl(self._getpath(path_parts[:-1]))
            dirents, locks = list_directory(list_url, _rev2optrev(rev), _rev2optrev(rev), 0, self.ctx)
            if locks.has_key(basename):
                lockinfo = locks[basename].owner
            if dirents.has_key(basename):
                size_in_rev = dirents[basename].size

        # Special handling for the 'svn_latest_log' scenario.
        ### FIXME: Don't like this hack.  We should just introduce
        ### something more direct in the vclib API.
        if options.get("svn_latest_log", 0):
            dir_lh_rev, dir_c_rev = self._get_last_history_rev(path_parts, rev)
            date, author, log, revprops, changes = self._revinfo(dir_lh_rev)
            return [vclib.Revision(dir_lh_rev, str(dir_lh_rev), date, author, None, log, size_in_rev, lockinfo)]

        def _access_checker(check_path, check_rev):
            return vclib.check_path_access(self, _path_parts(check_path), path_type, check_rev)

        # It's okay if we're told to not show all logs on a file -- all
        # the revisions should match correctly anyway.
        lc = LogCollector(path, options.get("svn_show_all_dir_logs", 0), lockinfo, _access_checker)

        cross_copies = options.get("svn_cross_copies", 0)
        log_limit = 0
        if limit:
            log_limit = first + limit
        client_log(url, _rev2optrev(rev), _rev2optrev(1), log_limit, 1, cross_copies, lc.add_log, self.ctx)
        revs = lc.logs
        revs.sort()
        prev = None
        for rev in revs:
            # Swap out revision info with stuff from the cache (which is
            # authz-sanitized).
            rev.date, rev.author, rev.log, revprops, changes = self._revinfo(rev.number)
            rev.prev = prev
            prev = rev
        revs.reverse()

        if len(revs) < first:
            return []
        if limit:
            return revs[first : first + limit]
        return revs
Example #11
0
    def annotate(self, path_parts, rev, include_text=False):
        path = self._getpath(path_parts)
        if self.itemtype(path_parts, rev) != vclib.FILE:  # does auth-check
            raise vclib.Error("Path '%s' is not a file." % path)
        rev = self._getrev(rev)
        url = self._geturl(path)

        # Examine logs for the file to determine the oldest revision we are
        # permitted to see.
        log_options = {
            'svn_cross_copies': 1,
            'svn_show_all_dir_logs': 1,
        }
        revs = self.itemlog(path_parts, rev, vclib.SORTBY_REV, 0, 0,
                            log_options)
        oldest_rev = revs[-1].number

        # Now calculate the annotation data.  Note that we'll not
        # inherently trust the provided author and date, because authz
        # rules might necessitate that we strip that information out.
        blame_data = []

        def _blame_cb(line_no,
                      revision,
                      author,
                      date,
                      line,
                      pool,
                      blame_data=blame_data):
            prev_rev = None
            if revision > 1:
                prev_rev = revision - 1

            # If we have an invalid revision, clear the date and author
            # values.  Otherwise, if we have authz filtering to do, use the
            # revinfo cache to do so.
            if revision < 0:
                date = author = None
            elif self.auth:
                date, author, msg, revprops, changes = self._revinfo(revision)

            # Strip text if the caller doesn't want it.
            if not include_text:
                line = None
            blame_data.append(
                vclib.Annotation(line, line_no + 1, revision, prev_rev, author,
                                 date))

        client.blame2(url, _rev2optrev(rev), _rev2optrev(oldest_rev),
                      _rev2optrev(rev), _blame_cb, self.ctx)
        return blame_data, rev
Example #12
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."""

        dir_url = self._geturl(path)
        if path:
            key = str(rev) + '/' + path
        else:
            key = str(rev)
        dirents_locks = self._dirent_cache.get(key)
        if not dirents_locks:
            dirents, locks = list_directory(dir_url, _rev2optrev(rev),
                                            _rev2optrev(rev), 0, self.ctx)
            dirents_locks = [dirents, locks]
            self._dirent_cache[key] = dirents_locks
        return dirents_locks[0], dirents_locks[1]
  def _get_dirents(self, path, rev):
    """Return a 2-type of dirents and locks, possibly reading/writing
    from a local cache of that information."""

    dir_url = self._geturl(path)
    if path:
      key = str(rev) + '/' + path
    else:
      key = str(rev)
    dirents_locks = self._dirent_cache.get(key)
    if not dirents_locks:
      dirents, locks = list_directory(dir_url, _rev2optrev(rev),
                                      _rev2optrev(rev), 0, self.ctx)
      dirents_locks = [dirents, locks]
      self._dirent_cache[key] = dirents_locks
    return dirents_locks[0], dirents_locks[1]
 def _get_last_history_rev(self, path_parts, rev):
   url = self._geturl(self._getpath(path_parts))
   optrev = _rev2optrev(rev)
   revisions = []
   def _info_cb(path, info, pool, retval=revisions):
     revisions.append(info.last_changed_rev)
   client.svn_client_info(url, optrev, optrev, _info_cb, 0, self.ctx)
   return revisions[0]
Example #15
0
def cat_to_tempfile(svnrepos, path, rev):
    """Check out file revision to temporary file"""
    fd, temp = tempfile.mkstemp()
    fp = os.fdopen(fd, 'wb')
    url = svnrepos._geturl(path)
    client.svn_client_cat(fp, url, _rev2optrev(rev), svnrepos.ctx)
    fp.close()
    return temp
Example #16
0
def cat_to_tempfile(svnrepos, path, rev):
    """Check out file revision to temporary file"""
    temp = tempfile.mktemp()
    stream = core.svn_stream_from_aprfile(temp)
    url = svnrepos._geturl(path)
    client.svn_client_cat(core.Stream(stream), url, _rev2optrev(rev), svnrepos.ctx)
    core.svn_stream_close(stream)
    return temp
Example #17
0
def cat_to_tempfile(svnrepos, path, rev):
    """Check out file revision to temporary file"""
    temp = tempfile.mktemp()
    stream = core.svn_stream_from_aprfile(temp)
    url = svnrepos._geturl(path)
    client.svn_client_cat(core.Stream(stream), url, _rev2optrev(rev),
                          svnrepos.ctx)
    core.svn_stream_close(stream)
    return temp
Example #18
0
  def annotate(self, path_parts, rev, include_text=False):
    path = self._getpath(path_parts)
    if self.itemtype(path_parts, rev) != vclib.FILE:  # does auth-check
      raise vclib.Error("Path '%s' is not a file." % path)
    rev = self._getrev(rev)
    url = self._geturl(path)

    # Examine logs for the file to determine the oldest revision we are
    # permitted to see.
    log_options = {
      'svn_cross_copies' : 1,
      'svn_show_all_dir_logs' : 1,
      }
    revs = self.itemlog(path_parts, rev, vclib.SORTBY_REV, 0, 0, log_options)
    oldest_rev = revs[-1].number

    # Now calculate the annotation data.  Note that we'll not
    # inherently trust the provided author and date, because authz
    # rules might necessitate that we strip that information out.
    blame_data = []

    def _blame_cb(line_no, revision, author, date,
                  line, pool, blame_data=blame_data):
      prev_rev = None
      if revision > 1:
        prev_rev = revision - 1

      # If we have an invalid revision, clear the date and author
      # values.  Otherwise, if we have authz filtering to do, use the
      # revinfo cache to do so.
      if revision < 0:
        date = author = None
      elif self.auth:
        date, author, msg, revprops, changes = self._revinfo(revision)

      # Strip text if the caller doesn't want it.
      if not include_text:
        line = None
      blame_data.append(vclib.Annotation(line, line_no + 1, revision, prev_rev,
                                         author, date))
      
    client.blame2(url, _rev2optrev(rev), _rev2optrev(oldest_rev),
                  _rev2optrev(rev), _blame_cb, self.ctx)
    return blame_data, rev
Example #19
0
    def _get_last_history_rev(self, path_parts, rev):
        url = self._geturl(self._getpath(path_parts))
        optrev = _rev2optrev(rev)
        revisions = []

        def _info_cb(path, info, pool, retval=revisions):
            revisions.append(info.last_changed_rev)

        client.svn_client_info(url, optrev, optrev, _info_cb, 0, self.ctx)
        return revisions[0]
  def annotate(self, path_parts, rev):
    path = self._getpath(path_parts)
    if self.itemtype(path_parts, rev) != vclib.FILE:  # does auth-check
      raise vclib.Error("Path '%s' is not a file." % path)
    rev = self._getrev(rev)
    url = self._geturl(path)

    blame_data = []

    def _blame_cb(line_no, revision, author, date,
                  line, pool, blame_data=blame_data):
      prev_rev = None
      if revision > 1:
        prev_rev = revision - 1
      blame_data.append(vclib.Annotation(line, line_no+1, revision, prev_rev,
                                         author, None))
      
    client.svn_client_blame(url, _rev2optrev(1), _rev2optrev(rev),
                            _blame_cb, self.ctx)

    return blame_data, rev
 def openfile(self, path_parts, rev):
   path = self._getpath(path_parts)
   if self.itemtype(path_parts, rev) != vclib.FILE:  # does auth-check
     raise vclib.Error("Path '%s' is not a file." % path)
   rev = self._getrev(rev)
   url = self._geturl(path)
   tmp_file = tempfile.mktemp()
   stream = core.svn_stream_from_aprfile(tmp_file)
   ### rev here should be the last history revision of the URL
   client.svn_client_cat(core.Stream(stream), url, _rev2optrev(rev), self.ctx)
   core.svn_stream_close(stream)
   return SelfCleanFP(tmp_file), self._get_last_history_rev(path_parts, rev)
  def itemlog(self, path_parts, rev, sortby, first, limit, options):
    assert sortby == vclib.SORTBY_DEFAULT or sortby == vclib.SORTBY_REV   
    path_type = self.itemtype(path_parts, rev) # does auth-check
    path = self._getpath(path_parts)
    rev = self._getrev(rev)
    url = self._geturl(path)

    # Use ls3 to fetch the lock status for this item.
    lockinfo = None
    basename = path_parts and path_parts[-1] or ""
    dirents, locks = list_directory(url, _rev2optrev(rev),
                                    _rev2optrev(rev), 0, self.ctx)
    if locks.has_key(basename):
      lockinfo = locks[basename].owner

    # It's okay if we're told to not show all logs on a file -- all
    # the revisions should match correctly anyway.
    lc = LogCollector(path, options.get('svn_show_all_dir_logs', 0), lockinfo)

    cross_copies = options.get('svn_cross_copies', 0)
    log_limit = 0
    if limit:
      log_limit = first + limit
    client.svn_client_log2([url], _rev2optrev(rev), _rev2optrev(1),
                           log_limit, 1, not cross_copies,
                           lc.add_log, self.ctx)
    revs = lc.logs
    revs.sort()
    prev = None
    for rev in revs:
      rev.prev = prev
      prev = rev
    revs.reverse()

    if len(revs) < first:
      return []
    if limit:
      return revs[first:first+limit]
    return revs
Example #23
0
    def itemlog(self, path_parts, rev, sortby, first, limit, options):
        assert sortby == vclib.SORTBY_DEFAULT or sortby == vclib.SORTBY_REV
        path_type = self.itemtype(path_parts, rev)  # does auth-check
        path = self._getpath(path_parts)
        rev = self._getrev(rev)
        url = self._geturl(path)

        # Use ls3 to fetch the lock status for this item.
        lockinfo = None
        basename = path_parts and path_parts[-1] or ""
        dirents, locks = list_directory(url, _rev2optrev(rev),
                                        _rev2optrev(rev), 0, self.ctx)
        if locks.has_key(basename):
            lockinfo = locks[basename].owner

        # It's okay if we're told to not show all logs on a file -- all
        # the revisions should match correctly anyway.
        lc = LogCollector(path, options.get('svn_show_all_dir_logs', 0),
                          lockinfo)

        cross_copies = options.get('svn_cross_copies', 0)
        log_limit = 0
        if limit:
            log_limit = first + limit
        client_log(url, _rev2optrev(rev), _rev2optrev(1), log_limit,
                   cross_copies, lc.add_log, self.ctx)
        revs = lc.logs
        revs.sort()
        prev = None
        for rev in revs:
            rev.prev = prev
            prev = rev
        revs.reverse()

        if len(revs) < first:
            return []
        if limit:
            return revs[first:first + limit]
        return revs
Example #24
0
 def openfile(self, path_parts, rev, options):
     path = self._getpath(path_parts)
     if self.itemtype(path_parts, rev) != vclib.FILE:  # does auth-check
         raise vclib.Error("Path '%s' is not a file." % path)
     rev = self._getrev(rev)
     url = self._geturl(path)
     tmp_file = tempfile.mktemp()
     stream = core.svn_stream_from_aprfile(tmp_file)
     ### rev here should be the last history revision of the URL
     client.svn_client_cat(core.Stream(stream), url, _rev2optrev(rev),
                           self.ctx)
     core.svn_stream_close(stream)
     return SelfCleanFP(tmp_file), self._get_last_history_rev(
         path_parts, rev)
Example #25
0
    def _revinfo_fetch(self, rev, include_changed_paths=0):
        need_changes = include_changed_paths or self.auth
        revs = []

        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])

        optrev = _rev2optrev(rev)
        client_log(self.rootpath, optrev, optrev, 1, need_changes, 0, _log_cb,
                   self.ctx)
        return tuple(revs[0])
Example #26
0
    def _revinfo_raw(self, rev):
        # return 5-tuple (date, author, msg, revprops, changes)
        optrev = _rev2optrev(rev)
        revs = []

        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])

        client_log(self.rootpath, optrev, optrev, 1, 0, _log_cb, self.ctx)
        return tuple(revs[0])
Example #27
0
    def itemlog(self, path_parts, rev, sortby, first, limit, options):
        assert sortby == vclib.SORTBY_DEFAULT or sortby == vclib.SORTBY_REV
        path_type = self.itemtype(path_parts, rev)  # does auth-check
        path = self._getpath(path_parts)
        rev = self._getrev(rev)
        url = self._geturl(path)

        # If this is a file, fetch the lock status and size (as of REV)
        # for this item.
        lockinfo = size_in_rev = None
        if path_type == vclib.FILE:
            basename = path_parts[-1]
            list_url = self._geturl(self._getpath(path_parts[:-1]))
            dirents, locks = list_directory(list_url, _rev2optrev(rev),
                                            _rev2optrev(rev), 0, self.ctx)
            if locks.has_key(basename):
                lockinfo = locks[basename].owner
            if dirents.has_key(basename):
                size_in_rev = dirents[basename].size

        # Special handling for the 'svn_latest_log' scenario.
        ### FIXME: Don't like this hack.  We should just introduce
        ### something more direct in the vclib API.
        if options.get('svn_latest_log', 0):
            dir_lh_rev, dir_c_rev = self._get_last_history_rev(path_parts, rev)
            date, author, log, revprops, changes = self._revinfo(dir_lh_rev)
            return [
                vclib.Revision(dir_lh_rev, str(dir_lh_rev), date, author, None,
                               log, size_in_rev, lockinfo)
            ]

        def _access_checker(check_path, check_rev):
            return vclib.check_path_access(self, _path_parts(check_path),
                                           path_type, check_rev)

        # It's okay if we're told to not show all logs on a file -- all
        # the revisions should match correctly anyway.
        lc = LogCollector(path, options.get('svn_show_all_dir_logs', 0),
                          lockinfo, _access_checker)

        cross_copies = options.get('svn_cross_copies', 0)
        log_limit = 0
        if limit:
            log_limit = first + limit
        client_log(url, _rev2optrev(rev), _rev2optrev(1), log_limit, 1,
                   cross_copies, lc.add_log, self.ctx)
        revs = lc.logs
        revs.sort()
        prev = None
        for rev in revs:
            # Swap out revision info with stuff from the cache (which is
            # authz-sanitized).
            rev.date, rev.author, rev.log, revprops, changes \
                      = self._revinfo(rev.number)
            rev.prev = prev
            prev = rev
        revs.reverse()

        if len(revs) < first:
            return []
        if limit:
            return revs[first:first + limit]
        return revs
Example #28
0
  def _revinfo_fetch(self, rev, include_changed_paths=0):
    need_changes = include_changed_paths or self.auth
    revs = []
    
    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])

    optrev = _rev2optrev(rev)
    client_log(self.rootpath, optrev, optrev, 1, need_changes, 0,
               _log_cb, self.ctx)
    return tuple(revs[0])
  def _revinfo_raw(self, rev):
    # return 5-tuple (date, author, message, changes)
    optrev = _rev2optrev(rev)
    revs = []

    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])

    client.svn_client_log([self.rootpath], optrev, optrev,
                          1, 0, _log_cb, self.ctx)
    return revs[0][0], revs[0][1], revs[0][2], revs[0][3]
Example #30
0
  def _revinfo_raw(self, rev):
    # return 5-tuple (date, author, msg, revprops, changes)
    optrev = _rev2optrev(rev)
    revs = []

    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])

    client_log(self.rootpath, optrev, optrev, 1, 0, _log_cb, self.ctx)
    return tuple(revs[0])