Ejemplo n.º 1
0
    def get_changes(self):
        root = fs.revision_root(self.fs_ptr, self.rev)
        editor = repos.RevisionChangeCollector(self.fs_ptr, self.rev)
        e_ptr, e_baton = delta.make_editor(editor)
        repos.svn_repos_replay(root, e_ptr, e_baton)

        idx = 0
        # Variables to record copy/deletes for later move detection
        copies, deletions = {}, {}
        changes = []
        for path, change in core._as_list(editor.changes.items()):
            if not self.authz.has_permission(path):
                # FIXME: what about base_path?
                continue
            if not path.startswith(self.scope[1:]):
                continue
            base_path = None
            if change.base_path:
                if change.base_path.startswith(self.scope):
                    base_path = change.base_path[len(self.scope):]
                else:
                    base_path = None
            action = ''
            if change.action == repos.CHANGE_ACTION_DELETE:
                action = Changeset.DELETE
                # Save off the index within changes of this deletion
                deletions[change.base_path] = idx
            elif change.added:
                if change.base_path and change.base_rev:
                    action = Changeset.COPY
                    # Save off the index within changes of this copy
                    copies[change.base_path] = idx
                else:
                    action = Changeset.ADD
            else:
                action = Changeset.EDIT
            kind = _kindmap[change.item_kind]
            path = path[len(self.scope) - 1:]
            changes.append([path, kind, action, base_path, change.base_rev])
            idx += 1

        # Detect moves by checking for copies whose source was deleted in this
        # change set.
        moves = set()
        for k, v in core._as_list(copies.items()):
            if k in deletions:
                changes[v][2] = Changeset.MOVE
                # Record the index of the now redundant delete action.
                moves.add(deletions[k])

        for i, change in enumerate(changes):
            # Do not return the 'delete' changes that were part of moves.
            if i not in moves:
                yield tuple(change)
Ejemplo n.º 2
0
 def props_changed(path, propchanges):
     for (name, value) in core._as_list(propchanges.items()):
         (kind, _) = core.svn_property_kind(name)
         if kind != core.svn_prop_regular_kind:
             continue
         got_prop_changes.append(
             (path[len(self.path) + 1:], name, value))
Ejemplo n.º 3
0
    def test_mergeinfo_leakage__incorrect_range_t_refcounts(self):
        """Ensure that the ref counts on svn_merge_range_t objects returned by
       svn_mergeinfo_parse() are correct."""
        # When reference counting is working properly, each svn_merge_range_t in
        # the returned mergeinfo will have a ref count of 1...
        mergeinfo = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO1)
        for (path, rangelist) in core._as_list(mergeinfo.items()):
            # ....and now 2 (incref during iteration of rangelist)

            for (i, r) in enumerate(rangelist):
                # ....and now 3 (incref during iteration of each range object)

                refcount = sys.getrefcount(r)
                # ....and finally, 4 (getrefcount() also increfs)
                expected = 4

                # Note: if path and index are not '/trunk' and 0 respectively, then
                # only some of the range objects are leaking, which is, as far as
                # leaks go, even more impressive.
                self.assertEqual(refcount, expected, (
                    "Memory leak!  Expected a ref count of %d for svn_merge_range_t "
                    "object, but got %d instead (path: %s, index: %d).  Probable "
                    "cause: incorrect Py_INCREF/Py_DECREF usage in libsvn_swig_py/"
                    "swigutil_py.c." % (expected, refcount, path, i)))

        del mergeinfo
        gc.collect()
Ejemplo n.º 4
0
 def receiver(log_entry, pool):
     called[0] = True
     self.assertEqual(log_entry.revision, rev)
     if discover_changed_paths:
         self.assertEqual(core._as_list(log_entry.changed_paths.keys()),
                          [b'/bla3'])
         changed_path = log_entry.changed_paths[b'/bla3']
         self.assertTrue(
             changed_path.action in [b'A', b'D', b'R', b'M'])
         self.assertEqual(changed_path.copyfrom_path, None)
         self.assertEqual(changed_path.copyfrom_rev, -1)
     else:
         self.assertEqual(log_entry.changed_paths, None)
     if log_revprops is None:
         self.assertEqual(log_entry.revprops, revprops)
     elif len(log_revprops) == 0:
         self.assertTrue(log_entry.revprops == None
                         or len(log_entry.revprops) == 0)
     else:
         revprop_names = sorted(log_entry.revprops.keys())
         log_revprops.sort()
         self.assertEqual(revprop_names, log_revprops)
         for i in log_revprops:
             self.assertEqual(log_entry.revprops[i],
                              revprops[i],
                              msg="%s != %s on %s" %
                              (log_entry.revprops[i], revprops[i],
                               (log_revprops, discover_changed_paths)))
Ejemplo n.º 5
0
 def receiver(changed_paths, revision, author, date, message, pool):
   receiver_called[0] = True
   self.assertEqual(revision, info.revision)
   self.assertEqual(author, info.author)
   self.assertEqual(date, info.date)
   self.assertEqual(message, revprops[b'svn:log'])
   for (path, change) in core._as_list(changed_paths.items()):
     path = path.lstrip(b'/')
     self.assertTrue(path in all_paths)
     if path in to_delete:
       self.assertEqual(change.action, b'D')
     elif path in to_mkdir or path in to_add:
       self.assertEqual(change.action, b'A')
     elif path in to_dir_prop or path in to_file_prop:
       self.assertEqual(change.action, b'M')
Ejemplo n.º 6
0
    def test_get_logs(self):
        """Test scope of get_logs callbacks"""
        logs = []

        def addLog(paths, revision, author, date, message, pool):
            if paths is not None:
                logs.append(paths)

        # Run get_logs
        repos.get_logs(self.repos, [b'/'], self.rev, 0, True, 0, addLog)

        # Count and verify changes
        change_count = 0
        for log in logs:
            for path_changed in core._as_list(log.values()):
                change_count += 1
                path_changed.assert_valid()
        self.assertEqual(logs[2][b"/tags/v1.1"].action, b"A")
        self.assertEqual(logs[2][b"/tags/v1.1"].copyfrom_path,
                         b"/branches/v1x")
        self.assertEqual(len(logs), 12)
        self.assertEqual(change_count, 19)
Ejemplo n.º 7
0
 def get_properties(self):
     props = fs.node_proplist(self.root, self.scoped_path)
     for name, value in core._as_list(props.items()):
         props[name] = value
     return props
Ejemplo n.º 8
0
#
# diff.py: public Python interface for diff components
#
# Subversion is a tool for revision control.
# See http://subversion.apache.org for more information.
#
######################################################################
#    Licensed to the Apache Software Foundation (ASF) under one
#    or more contributor license agreements.  See the NOTICE file
#    distributed with this work for additional information
#    regarding copyright ownership.  The ASF licenses this file
#    to you under the Apache License, Version 2.0 (the
#    "License"); you may not use this file except in compliance
#    with the License.  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing,
#    software distributed under the License is distributed on an
#    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#    KIND, either express or implied.  See the License for the
#    specific language governing permissions and limitations
#    under the License.
######################################################################

from libsvn.diff import *
from svn.core import _unprefix_names, _as_list
_unprefix_names(locals(), 'svn_diff_')
__all__ = [x for x in _as_list(locals()) if x.lower().startswith('svn_')]
del _unprefix_names
Ejemplo n.º 9
0
def entries(root, path, pool=None):
  "Call dir_entries returning a dictionary mappings names to IDs."
  e = dir_entries(root, path, pool)
  for name, entry in _as_list(e.items()):
    e[name] = dirent_t_id_get(entry)
  return e
Ejemplo n.º 10
0
  def test_delta_driver_commit(self):
    # Setup paths we'll commit in this test.
    to_delete = [b'trunk/README.txt', b'trunk/dir1/dir2']
    to_mkdir = [b'test_delta_driver_commit.d', b'test_delta_driver_commit2.d']
    to_add = [b'test_delta_driver_commit', b'test_delta_driver_commit2']
    to_dir_prop = [b'trunk/dir1/dir3', b'test_delta_driver_commit2.d']
    to_file_prop = [b'trunk/README2.txt', b'test_delta_driver_commit2']
    all_paths = {}
    for i in to_delete + to_mkdir + to_add + to_dir_prop + to_file_prop:
      all_paths[i] = True
    # base revision for the commit
    revision = fs.youngest_rev(self.fs)

    commit_info = []
    def commit_cb(info, pool):
      commit_info.append(info)
    revprops = {b"svn:log": b"foobar", b"testprop": b""}
    (editor, edit_baton) = ra.get_commit_editor3(self.ra_ctx, revprops,
                                                 commit_cb, None, False)
    try:
      def driver_cb(parent, path, pool):
        self.assertTrue(path in all_paths)
        dir_baton = file_baton = None
        if path in to_delete:
          # Leave dir_baton alone, as it must be None for delete.
          editor.delete_entry(path, revision, parent, pool)
        elif path in to_mkdir:
          dir_baton = editor.add_directory(path, parent,
                                           None, -1, # copyfrom
                                           pool)
        elif path in to_add:
          file_baton = editor.add_file(path, parent,
                                       None, -1, # copyfrom
                                       pool)
        # wc.py:test_commit tests apply_textdelta .
        if path in to_dir_prop:
          if dir_baton is None:
            dir_baton = editor.open_directory(path, parent, revision, pool)
          editor.change_dir_prop(dir_baton,
                                 b'test_delta_driver_commit', b'foo', pool)
        elif path in to_file_prop:
          if file_baton is None:
            file_baton = editor.open_file(path, parent, revision, pool)
          editor.change_file_prop(file_baton,
                                  b'test_delta_driver_commit', b'foo', pool)
        if file_baton is not None:
          editor.close_file(file_baton, None, pool)
        return dir_baton
      delta.path_driver(editor, edit_baton, -1, core._as_list(all_paths.keys()), driver_cb)
      editor.close_edit(edit_baton)
    except:
      try:
        editor.abort_edit(edit_baton)
      except:
        # We already have an exception in progress, not much we can do
        # about this.
        pass
      raise
    info = commit_info[0]

    if info.author is not None:
      revprops[b'svn:author'] = info.author
    revprops[b'svn:date'] = info.date
    self.assertEqual(ra.rev_proplist(self.ra_ctx, info.revision), revprops)

    receiver_called = [False]
    def receiver(changed_paths, revision, author, date, message, pool):
      receiver_called[0] = True
      self.assertEqual(revision, info.revision)
      self.assertEqual(author, info.author)
      self.assertEqual(date, info.date)
      self.assertEqual(message, revprops[b'svn:log'])
      for (path, change) in core._as_list(changed_paths.items()):
        path = path.lstrip(b'/')
        self.assertTrue(path in all_paths)
        if path in to_delete:
          self.assertEqual(change.action, b'D')
        elif path in to_mkdir or path in to_add:
          self.assertEqual(change.action, b'A')
        elif path in to_dir_prop or path in to_file_prop:
          self.assertEqual(change.action, b'M')
    ra.get_log(self.ra_ctx, [b''], info.revision, info.revision,
               0,                       # limit
               True,                    # discover_changed_paths
               True,                    # strict_node_history
               receiver)
    self.assertTrue(receiver_called[0])
Ejemplo n.º 11
0
 def test_entries_read(self):
     entries = wc.entries_read(self.wc, True)
     keys = core._as_list(entries.keys())
     keys.sort()
     self.assertEqual([b'', b'branches', b'tags', b'trunk'], keys)