Esempio n. 1
0
def copy_delete_unreadable_child(sbox):
    "copy, then rm at-src-unreadable child"

    # Prepare the source: Greek tree (r1), cp+rm (r2).
    sbox.build(create_wc=False)
    svntest.actions.run_and_verify_svnmucc(
        None, [], "-m", "r2", "-U", sbox.repo_url, "cp", "HEAD", "/", "branch", "rm", "branch/A"
    )

    # Create the destination.
    dest_sbox = sbox.clone_dependent()
    dest_sbox.build(create_wc=False, empty=True)
    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    # Lock down the source.
    write_restrictive_svnserve_conf(sbox.repo_dir, anon_access="read")
    src_authz = sbox.authz_name()
    write_authz_file(sbox, None, prefixed_rules={src_authz + ":/": "* = r", src_authz + ":/A": "* ="})

    dest_url = dest_sbox.file_protocol_repo_url()
    run_init(dest_url, sbox.repo_url)
    run_sync(dest_url)

    # sanity check
    svntest.actions.run_and_verify_svn(["iota\n"], [], "ls", dest_url + "/branch@2")
def basic_authz(sbox):
    "verify that unreadable content is not synced"

    sbox.build(create_wc=False)

    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    dest_sbox.build(create_wc=False, empty=True)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    run_init(dest_sbox.repo_url, sbox.repo_url)

    src_authz = sbox.authz_name()
    dst_authz = dest_sbox.authz_name()
    write_authz_file(sbox,
                     None,
                     prefixed_rules={
                         src_authz + ':/': '* = r',
                         src_authz + ':/A/B': '* =',
                         dst_authz + ':/': '* = rw',
                     })

    run_sync(dest_sbox.repo_url)

    lambda_url = dest_sbox.repo_url + '/A/B/lambda'
    iota_url = dest_sbox.repo_url + '/iota'

    # this file should have been blocked by authz
    svntest.actions.run_and_verify_svn([], svntest.verify.AnyOutput, 'cat',
                                       lambda_url)
    # this file should have been synced
    svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], 'cat',
                                       iota_url)
Esempio n. 3
0
def basic_authz(sbox):
    "verify that unreadable content is not synced"

    sbox.build("svnsync-basic-authz")

    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    build_repos(dest_sbox)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    run_init(dest_sbox.repo_url, sbox.repo_url)

    svntest.main.file_write(
        sbox.authz_file, "[svnsync-basic-authz:/]\n"
        "* = r\n"
        "\n"
        "[svnsync-basic-authz:/A/B]\n"
        "* = \n"
        "\n"
        "[svnsync-basic-authz-1:/]\n"
        "* = rw\n")

    run_sync(dest_sbox.repo_url)

    lambda_url = dest_sbox.repo_url + '/A/B/lambda'

    # this file should have been blocked by authz
    svntest.actions.run_and_verify_svn(None, [], svntest.verify.AnyOutput,
                                       'cat', lambda_url)
Esempio n. 4
0
def authz_recursive_ls(sbox):
    "recursive ls with private subtrees"

    sbox.build(create_wc=False)
    local_dir = sbox.wc_dir
    write_restrictive_svnserve_conf(sbox.repo_dir)

    write_authz_file(sbox, {
        '/': '* = r',
        '/A/B/E': '* =',
        '/A/mu': '* =',
    })
    expected_entries = [
        'A/',
        'A/B/',
        'A/B/F/',
        'A/B/lambda',
        'A/C/',
        'A/D/',
        'A/D/G/',
        'A/D/G/pi',
        'A/D/G/rho',
        'A/D/G/tau',
        'A/D/H/',
        'A/D/H/chi',
        'A/D/H/omega',
        'A/D/H/psi',
        'A/D/gamma',
        'iota',
    ]
    svntest.actions.run_and_verify_svn(
        'recursive ls from /', map(lambda x: x + '\n', expected_entries), [],
        'ls', '-R', sbox.repo_url)
Esempio n. 5
0
def basic_authz(sbox):
    "verify that unreadable content is not synced"

    sbox.build(create_wc=False)

    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    dest_sbox.build(create_wc=False, empty=True)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    run_init(dest_sbox.repo_url, sbox.repo_url)

    src_authz = sbox.authz_name()
    dst_authz = dest_sbox.authz_name()
    write_authz_file(
        sbox, None, prefixed_rules={src_authz + ":/": "* = r", src_authz + ":/A/B": "* =", dst_authz + ":/": "* = rw"}
    )

    run_sync(dest_sbox.repo_url)

    lambda_url = dest_sbox.repo_url + "/A/B/lambda"
    iota_url = dest_sbox.repo_url + "/iota"

    # this file should have been blocked by authz
    svntest.actions.run_and_verify_svn([], svntest.verify.AnyOutput, "cat", lambda_url)
    # this file should have been synced
    svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], "cat", iota_url)
def copy_delete_unreadable_child(sbox):
  "copy, then rm at-src-unreadable child"

  # Prepare the source: Greek tree (r1), cp+rm (r2).
  sbox.build(create_wc = False)
  svntest.actions.run_and_verify_svnmucc(None, [],
                                         '-m', 'r2',
                                         '-U', sbox.repo_url,
                                         'cp', 'HEAD', '/', 'branch',
                                         'rm', 'branch/A')

  # Create the destination.
  dest_sbox = sbox.clone_dependent()
  dest_sbox.build(create_wc=False, empty=True)
  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  # Lock down the source.
  write_restrictive_svnserve_conf(sbox.repo_dir, anon_access='read')
  src_authz = sbox.authz_name()
  write_authz_file(sbox, None,
                   prefixed_rules = {
                       src_authz + ':/':  '* = r',
                       src_authz + ':/A': '* =',
                       })

  dest_url = dest_sbox.file_protocol_repo_url()
  run_init(dest_url, sbox.repo_url)
  run_sync(dest_url)

  # sanity check
  svntest.actions.run_and_verify_svn(["iota\n"], [],
                                     'ls', dest_url+'/branch@2')
Esempio n. 7
0
def authz_open_root(sbox):
  "authz issue #2486 - open root"

  sbox.build()

  write_authz_file(sbox, {"/": "", "/A": "jrandom = rw"})

  write_restrictive_svnserve_conf(sbox.repo_dir)

  # we have write access in folder /A, but not in root. Test on too
  # restrictive access needed in open_root by modifying a file in /A
  wc_dir = sbox.wc_dir

  mu_path = os.path.join(wc_dir, 'A', 'mu')
  svntest.main.file_append(mu_path, "hi")

  # Create expected output tree.
  expected_output = svntest.wc.State(wc_dir, {
    'A/mu' : Item(verb='Sending'),
    })

  # Commit the one file.
  svntest.actions.run_and_verify_commit(wc_dir,
                                        expected_output,
                                        None,
                                        None,
                                        mu_path)
Esempio n. 8
0
def authz_aliases(sbox):
  "test authz for aliases"

  sbox.build(create_wc = False)

  write_restrictive_svnserve_conf(sbox.repo_dir)

  if sbox.repo_url.startswith("http"):
    expected_err = ".*403 Forbidden.*"
  else:
    expected_err = ".*svn: Authorization failed.*"

  write_authz_file(sbox, { "/" : "* = r",
                           "/A/B" : "&jray = rw" },
                         { "aliases" : 'jray = jrandom' } )

  root_url = sbox.repo_url
  A_url = root_url + '/A'
  B_url = A_url + '/B'
  iota_url = root_url + '/iota'

  # copy a remote file, target is readonly for jconstant: should fail
  svntest.actions.run_and_verify_svn(None,
                                     None, expected_err,
                                     'cp',
                                     '--username', svntest.main.wc_author2,
                                     '-m', 'logmsg',
                                     iota_url, B_url)

  # try the same action, but as user jray (alias of jrandom), should work.
  svntest.actions.run_and_verify_svn(None,
                                     None, [],
                                     'cp',
                                     '-m', 'logmsg',
                                     iota_url, B_url)
Esempio n. 9
0
def copy_delete_unreadable_child(sbox):
  "copy, then rm at-src-unreadable child"

  # Prepare the source: Greek tree (r1), cp+rm (r2).
  sbox.build("copy-delete-unreadable-child")
  svntest.actions.run_and_verify_svnmucc(None, None, [],
                                         '-m', 'r2',
                                         '-U', sbox.repo_url,
                                         'cp', 'HEAD', '/', 'branch',
                                         'rm', 'branch/A')

  # Create the destination.
  dest_sbox = sbox.clone_dependent()
  build_repos(dest_sbox)
  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  # Lock down the source.
  authz = sbox.authz_name()
  write_restrictive_svnserve_conf(sbox.repo_dir, anon_access='read')
  svntest.main.file_write(sbox.authz_file,
      "[%s:/]\n"
      "* = r\n"
      "[%s:/A]\n"
      "* =  \n"
      % (authz, authz))

  dest_url = svntest.main.file_scheme_prefix \
                    + urllib.pathname2url(os.path.abspath(dest_sbox.repo_dir))
  run_init(dest_url, sbox.repo_url)
  run_sync(dest_url)

  # sanity check
  svntest.actions.run_and_verify_svn(None,
                                     ["iota\n"], [],
                                     'ls', dest_url+'/branch@2')
Esempio n. 10
0
def authz_open_directory(sbox):
    "authz issue #2486 - open directory"

    sbox.build()

    write_authz_file(sbox, {
        "/": "*=rw",
        "/A/B": "*=",
        "/A/B/E": "jrandom = rw"
    })

    write_restrictive_svnserve_conf(sbox.repo_dir)

    # we have write access in folder /A/B/E, but not in /A/B. Test on too
    # restrictive access needed in open_directory by moving file /A/mu to
    # /A/B/E
    wc_dir = sbox.wc_dir

    mu_path = os.path.join(wc_dir, 'A', 'mu')
    E_path = os.path.join(wc_dir, 'A', 'B', 'E')

    svntest.main.run_svn(None, 'mv', mu_path, E_path)

    # Create expected output tree.
    expected_output = svntest.wc.State(wc_dir, {
        'A/mu': Item(verb='Deleting'),
        'A/B/E/mu': Item(verb='Adding'),
    })

    # Commit the working copy.
    svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
                                          wc_dir)
Esempio n. 11
0
def authz_open_directory(sbox):
  "authz issue #2486 - open directory"

  sbox.build()

  write_authz_file(sbox, {"/": "*=rw", "/A/B": "*=", "/A/B/E": "jrandom = rw"})

  write_restrictive_svnserve_conf(sbox.repo_dir)

  # we have write access in folder /A/B/E, but not in /A/B. Test on too
  # restrictive access needed in open_directory by moving file /A/mu to
  # /A/B/E
  wc_dir = sbox.wc_dir

  mu_path = os.path.join(wc_dir, 'A', 'mu')
  E_path = os.path.join(wc_dir, 'A', 'B', 'E')

  svntest.main.run_svn(None, 'mv', mu_path, E_path)

  # Create expected output tree.
  expected_output = svntest.wc.State(wc_dir, {
    'A/mu' : Item(verb='Deleting'),
    'A/B/E/mu' : Item(verb='Adding'),
    })

  # Commit the working copy.
  svntest.actions.run_and_verify_commit(wc_dir,
                                        expected_output,
                                        None,
                                        None,
                                        wc_dir)
Esempio n. 12
0
def authz_access_required_at_repo_root2(sbox):
    "more authz issue #3242 - update to renamed file"

    sbox.build(create_wc=False)
    root_url = sbox.repo_url

    # Now we get all restrictive.
    write_authz_file(sbox, {'/': '* =', '/A': 'jrandom = rw'})
    write_restrictive_svnserve_conf(sbox.repo_dir)

    # Rename a file.
    svntest.main.run_svn(None, 'mv', '-m',
                         'rename file in readable writable space',
                         root_url + '/A/B/E/alpha',
                         root_url + '/A/B/E/alpha-renamed')

    # Check out original greek sub tree below /A/B/E
    # and update it to the above rename.
    wc_dir = sbox.add_wc_path('ABE')
    os.mkdir(wc_dir)
    svntest.main.run_svn(None, 'co', '-r', '1', root_url + '/A/B/E', wc_dir)
    svntest.main.run_svn(None, 'up', wc_dir)

    # Rename a directory.
    svntest.main.run_svn(None, 'mv', '-m',
                         'rename diretory in readable writable space',
                         root_url + '/A/D/H', root_url + '/A/D/a g e')

    # Check out original greek sub tree below /A/D
    # and update it to the above rename.
    wc_dir = sbox.add_wc_path('AD')
    os.mkdir(wc_dir)
    svntest.main.run_svn(None, 'co', '-r', '1', root_url + '/A/D', wc_dir)
    svntest.main.run_svn(None, 'up', wc_dir)
Esempio n. 13
0
def authz_aliases(sbox):
    "test authz for aliases"

    sbox.build(create_wc=False)

    write_restrictive_svnserve_conf(sbox.repo_dir)

    if sbox.repo_url.startswith("http"):
        expected_err = ".*403 Forbidden.*"
    else:
        expected_err = ".*svn: Authorization failed.*"

    write_authz_file(sbox, {
        "/": "* = r",
        "/A/B": "&jray = rw"
    }, {"aliases": 'jray = jrandom'})

    root_url = sbox.repo_url
    A_url = root_url + '/A'
    B_url = A_url + '/B'
    iota_url = root_url + '/iota'

    # copy a remote file, target is readonly for jconstant: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'cp',
                                       '--username', svntest.main.wc_author2,
                                       '-m', 'logmsg', iota_url, B_url)

    # try the same action, but as user jray (alias of jrandom), should work.
    svntest.actions.run_and_verify_svn(None, None, [], 'cp', '-m', 'logmsg',
                                       iota_url, B_url)
Esempio n. 14
0
def copy_delete_unreadable_child(sbox):
    "copy, then rm at-src-unreadable child"

    # Prepare the source: Greek tree (r1), cp+rm (r2).
    sbox.build("copy-delete-unreadable-child")
    svntest.actions.run_and_verify_svnmucc(None, None, [], '-m', 'r2', '-U',
                                           sbox.repo_url, 'cp', 'HEAD', '/',
                                           'branch', 'rm', 'branch/A')

    # Create the destination.
    dest_sbox = sbox.clone_dependent()
    build_repos(dest_sbox)
    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    # Lock down the source.
    authz = sbox.authz_name()
    write_restrictive_svnserve_conf(sbox.repo_dir, anon_access='read')
    svntest.main.file_write(
        sbox.authz_file, "[%s:/]\n"
        "* = r\n"
        "[%s:/A]\n"
        "* =  \n" % (authz, authz))

    dest_url = svntest.main.file_scheme_prefix \
                      + urllib.pathname2url(os.path.abspath(dest_sbox.repo_dir))
    run_init(dest_url, sbox.repo_url)
    run_sync(dest_url)

    # sanity check
    svntest.actions.run_and_verify_svn(None, ["iota\n"], [], 'ls',
                                       dest_url + '/branch@2')
Esempio n. 15
0
def authz_partial_export_test(sbox):
    "test authz for export with unreadable subfolder"

    sbox.build(create_wc=False, read_only=True)
    local_dir = sbox.wc_dir

    # cleanup remains of a previous test run.
    svntest.main.safe_rmtree(local_dir)

    write_restrictive_svnserve_conf(sbox.repo_dir)

    # 1st part: disable read access on folder A/B, export should not
    # download this folder

    # write an authz file with *= on /A/B
    write_authz_file(sbox, {"/": "* = r", "/A/B": "* ="})

    # export a working copy, should not dl /A/B
    expected_output = svntest.main.greek_state.copy()
    expected_output.wc_dir = local_dir
    expected_output.desc[''] = Item()
    expected_output.tweak(status='A ', contents=None)
    expected_output.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
                           'A/B/E/beta', 'A/B/F')

    expected_wc = svntest.main.greek_state.copy()
    expected_wc.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
                       'A/B/E/beta', 'A/B/F')

    svntest.actions.run_and_verify_export(sbox.repo_url, local_dir,
                                          expected_output, expected_wc)
def basic_authz(sbox):
  "verify that unreadable content is not synced"

  sbox.build("svnsync-basic-authz")

  write_restrictive_svnserve_conf(sbox.repo_dir)

  dest_sbox = sbox.clone_dependent()
  build_repos(dest_sbox)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  run_init(dest_sbox.repo_url, sbox.repo_url)

  svntest.main.file_write(sbox.authz_file,
                          "[svnsync-basic-authz:/]\n"
                          "* = r\n"
                          "\n"
                          "[svnsync-basic-authz:/A/B]\n"
                          "* = \n"
                          "\n"
                          "[svnsync-basic-authz-1:/]\n"
                          "* = rw\n")

  run_sync(dest_sbox.repo_url)

  lambda_url = dest_sbox.repo_url + '/A/B/lambda'

  # this file should have been blocked by authz
  svntest.actions.run_and_verify_svn(None,
                                     [], svntest.verify.AnyOutput,
                                     'cat',
                                     lambda_url)
Esempio n. 17
0
def authz_partial_export_test(sbox):
  "test authz for export with unreadable subfolder"

  sbox.build(create_wc = False, read_only = True)
  local_dir = sbox.wc_dir

  # cleanup remains of a previous test run.
  svntest.main.safe_rmtree(local_dir)

  write_restrictive_svnserve_conf(sbox.repo_dir)

  # 1st part: disable read access on folder A/B, export should not
  # download this folder

  # write an authz file with *= on /A/B
  write_authz_file(sbox, { "/": "* = r", "/A/B": "* =" })

  # export a working copy, should not dl /A/B
  expected_output = svntest.main.greek_state.copy()
  expected_output.wc_dir = local_dir
  expected_output.desc[''] = Item()
  expected_output.tweak(status='A ', contents=None)
  expected_output.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
                         'A/B/E/beta', 'A/B/F')

  expected_wc = svntest.main.greek_state.copy()
  expected_wc.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
                     'A/B/E/beta', 'A/B/F')

  svntest.actions.run_and_verify_export(sbox.repo_url, local_dir,
                                        expected_output,
                                        expected_wc)
Esempio n. 18
0
def authz_checkout_test(sbox):
    "test authz for checkout"

    sbox.build(create_wc=False, read_only=True)
    local_dir = sbox.wc_dir

    write_restrictive_svnserve_conf(sbox.repo_dir)

    # 1st part: disable all read access, checkout should fail

    # write an authz file with *= on /
    if sbox.repo_url.startswith('http'):
        expected_err = ".*403 Forbidden.*"
    else:
        expected_err = ".*svn: Authorization failed.*"

    write_authz_file(sbox, {"/": "* ="})

    # checkout a working copy, should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'co',
                                       sbox.repo_url, local_dir)

    # 2nd part: now enable read access

    write_authz_file(sbox, {"/": "* = r"})

    # checkout a working copy, should succeed because we have read access
    expected_output = svntest.main.greek_state.copy()
    expected_output.wc_dir = local_dir
    expected_output.tweak(status='A ', contents=None)

    expected_wc = svntest.main.greek_state

    svntest.actions.run_and_verify_checkout(sbox.repo_url, local_dir,
                                            expected_output, expected_wc)
Esempio n. 19
0
def copy_delete_unreadable_child(sbox):
    "copy, then rm at-src-unreadable child"

    # Prepare the source: Greek tree (r1), cp+rm (r2).
    sbox.build(create_wc=False)
    svntest.actions.run_and_verify_svnmucc(None, [], '-m', 'r2', '-U',
                                           sbox.repo_url, 'cp', 'HEAD', '/',
                                           'branch', 'rm', 'branch/A')

    # Create the destination.
    dest_sbox = sbox.clone_dependent()
    dest_sbox.build(create_wc=False, empty=True)
    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    # Lock down the source.
    write_restrictive_svnserve_conf(sbox.repo_dir, anon_access='read')
    src_authz = sbox.authz_name()
    write_authz_file(sbox,
                     None,
                     prefixed_rules={
                         src_authz + ':/': '* = r',
                         src_authz + ':/A': '* =',
                     })

    dest_url = dest_sbox.file_protocol_repo_url()
    run_init(dest_url, sbox.repo_url)
    run_sync(dest_url)

    # sanity check
    svntest.actions.run_and_verify_svn(["iota\n"], [], 'ls',
                                       dest_url + '/branch@2')
Esempio n. 20
0
def authz_validate(sbox):
    "test the authz validation rules"

    sbox.build(create_wc=False, read_only=True)

    write_restrictive_svnserve_conf(sbox.repo_dir)

    A_url = sbox.repo_url + '/A'

    # If any of the validate rules fail, the authz isn't loaded so there's no
    # access at all to the repository.

    # Test 1: Undefined group
    write_authz_file(sbox, {"/": "* = r", "/A/B": "@undefined_group = rw"})

    if sbox.repo_url.startswith("http"):
        expected_err = ".*[Ff]orbidden.*"
    elif sbox.repo_url.startswith("svn"):
        expected_err = ".*Invalid authz configuration"
    else:
        expected_err = ".*@undefined_group.*"

    # validation of this authz file should fail, so no repo access
    svntest.actions.run_and_verify_svn("ls remote folder", None, expected_err,
                                       'ls', A_url)

    # Test 2: Circular dependency
    write_authz_file(sbox, {"/": "* = r"}, {
        "groups":
        """admins = admin1, admin2, @devs
devs1 = @admins, dev1
devs2 = @admins, dev2
devs = @devs1, dev3, dev4"""
    })

    if sbox.repo_url.startswith("http"):
        expected_err = ".*[Ff]orbidden.*"
    elif sbox.repo_url.startswith("svn"):
        expected_err = ".*Invalid authz configuration"
    else:
        expected_err = ".*Circular dependency.*"

    # validation of this authz file should fail, so no repo access
    svntest.actions.run_and_verify_svn("ls remote folder", None, expected_err,
                                       'ls', A_url)

    # Test 3: Group including other group 2 times (issue 2684)
    write_authz_file(sbox, {"/": "* = r"}, {
        "groups":
        """admins = admin1, admin2
devs1 = @admins, dev1
devs2 = @admins, dev2
users = @devs1, @devs2, user1, user2"""
    })

    # validation of this authz file should fail, so no repo access
    svntest.actions.run_and_verify_svn("ls remote folder",
                                       ['B/\n', 'C/\n', 'D/\n', 'mu\n'], [],
                                       'ls', A_url)
Esempio n. 21
0
def authz_write_access(sbox):
    "test authz for write operations"

    sbox.build(create_wc=False)

    write_restrictive_svnserve_conf(sbox.repo_dir)

    if sbox.repo_url.startswith('http'):
        expected_err = ".*403 Forbidden.*"
    else:
        expected_err = ".*svn: Access denied.*"

    write_authz_file(sbox, {"/": "* = r", "/A/B": "* = rw", "/A/C": "* = rw"})

    root_url = sbox.repo_url
    A_url = root_url + '/A'
    B_url = A_url + '/B'
    C_url = A_url + '/C'
    E_url = B_url + '/E'
    mu_url = A_url + '/mu'
    iota_url = root_url + '/iota'
    lambda_url = B_url + '/lambda'
    D_url = A_url + '/D'

    # copy a remote file, target is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'cp', '-m',
                                       'logmsg', lambda_url, D_url)

    # copy a remote folder, target is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'cp', '-m',
                                       'logmsg', E_url, D_url)

    # delete a file, target is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'rm', '-m',
                                       'logmsg', iota_url)

    # delete a folder, target is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'rm', '-m',
                                       'logmsg', D_url)

    # create a folder, target is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'mkdir', '-m',
                                       'logmsg', A_url + '/newfolder')

    # move a remote file, source is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'mv', '-m',
                                       'logmsg', mu_url, C_url)

    # move a remote folder, source is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'mv', '-m',
                                       'logmsg', D_url, C_url)

    # move a remote file, target is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'mv', '-m',
                                       'logmsg', lambda_url, D_url)

    # move a remote folder, target is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'mv', '-m',
                                       'logmsg', B_url, D_url)
Esempio n. 22
0
def specific_deny_authz(sbox):
  "verify if specifically denied paths dont sync"

  sbox.build()

  dest_sbox = sbox.clone_dependent()
  build_repos(dest_sbox)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  run_init(dest_sbox.repo_url, sbox.repo_url)

  svntest.main.run_svn(None, "cp",
                       os.path.join(sbox.wc_dir, "A"),
                       os.path.join(sbox.wc_dir, "A_COPY")
                       )
  svntest.main.run_svn(None, "ci", "-mm", sbox.wc_dir)

  write_restrictive_svnserve_conf(sbox.repo_dir)

  # For mod_dav_svn's parent path setup we need per-repos permissions in
  # the authz file...
  if sbox.repo_url.startswith('http'):
    args = tuple(s.authz_name() for s in [sbox, sbox, sbox, dest_sbox])
    svntest.main.file_write(sbox.authz_file,
                            "[%s:/]\n"
                            "* = r\n"
                            "\n"
                            "[%s:/A]\n"
                            "* = \n"
                            "\n"
                            "[%s:/A_COPY/B/lambda]\n"
                            "* = \n"
                            "\n"
                            "[%s:/]\n"
                            "* = rw\n" % args)
  # Otherwise we can just go with the permissions needed for the source
  # repository.
  else:
    svntest.main.file_write(sbox.authz_file,
                            "[/]\n"
                            "* = r\n"
                            "\n"
                            "[/A]\n"
                            "* = \n"
                            "\n"
                            "[/A_COPY/B/lambda]\n"
                            "* = \n")

  run_sync(dest_sbox.repo_url)

  lambda_url = dest_sbox.repo_url + '/A_COPY/B/lambda'

  # this file should have been blocked by authz
  svntest.actions.run_and_verify_svn(None,
                                     [], svntest.verify.AnyOutput,
                                     'cat',
                                     lambda_url)
Esempio n. 23
0
def copy_from_unreadable_dir(sbox):
    "verify that copies from unreadable dirs work"

    sbox.build()

    B_url = sbox.repo_url + "/A/B"
    P_url = sbox.repo_url + "/A/P"

    # Set a property on the directory we're going to copy, and a file in it, to
    # confirm that they're transmitted when we later sync the copied directory
    svntest.actions.run_and_verify_svn(None, [], "pset", "foo", "bar", sbox.wc_dir + "/A/B/lambda")

    svntest.actions.run_and_verify_svn(None, [], "pset", "baz", "zot", sbox.wc_dir + "/A/B")

    svntest.actions.run_and_verify_svn(None, [], "ci", sbox.wc_dir + "/A/B", "-m", "log_msg")

    # Now copy that directory so we'll see it in our synced copy
    svntest.actions.run_and_verify_svn(None, [], "cp", B_url, P_url, "-m", "Copy B to P")

    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    dest_sbox.build(create_wc=False, empty=True)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    src_authz = sbox.authz_name()
    dst_authz = dest_sbox.authz_name()
    write_authz_file(
        sbox, None, prefixed_rules={src_authz + ":/": "* = r", src_authz + ":/A/B": "* =", dst_authz + ":/": "* = rw"}
    )

    run_init(dest_sbox.repo_url, sbox.repo_url)

    run_sync(dest_sbox.repo_url)

    expected_out = [
        "Changed paths:\n",
        "   A /A/P\n",
        "   A /A/P/E\n",
        "   A /A/P/E/alpha\n",
        "   A /A/P/E/beta\n",
        "   A /A/P/F\n",
        "   A /A/P/lambda\n",
        "\n",
        "\n",  # log message is stripped
    ]

    exit_code, out, err = svntest.main.run_svn(None, "log", "-r", "3", "-v", dest_sbox.repo_url)

    if err:
        raise SVNUnexpectedStderr(err)

    svntest.verify.compare_and_display_lines(None, "LOG", expected_out, out[2:11])

    svntest.actions.run_and_verify_svn(["bar\n"], [], "pget", "foo", dest_sbox.repo_url + "/A/P/lambda")

    svntest.actions.run_and_verify_svn(["zot\n"], [], "pget", "baz", dest_sbox.repo_url + "/A/P")
Esempio n. 24
0
def authz_validate(sbox):
  "test the authz validation rules"

  sbox.build(create_wc = False, read_only = True)

  write_restrictive_svnserve_conf(sbox.repo_dir)

  A_url = sbox.repo_url + '/A'

  # If any of the validate rules fail, the authz isn't loaded so there's no
  # access at all to the repository.

  # Test 1: Undefined group
  write_authz_file(sbox, { "/"  : "* = r",
                           "/A/B" : "@undefined_group = rw" })

  if sbox.repo_url.startswith("http"):
    expected_err = ".*403 Forbidden.*"
  else:
    expected_err = ".*@undefined_group.*"

  # validation of this authz file should fail, so no repo access
  svntest.actions.run_and_verify_svn("ls remote folder",
                                     None, expected_err,
                                     'ls',
                                     A_url)

  # Test 2: Circular dependency
  write_authz_file(sbox, { "/"  : "* = r" },
                         { "groups" : """admins = admin1, admin2, @devs
devs1 = @admins, dev1
devs2 = @admins, dev2
devs = @devs1, dev3, dev4""" })

  if sbox.repo_url.startswith("http"):
    expected_err = ".*403 Forbidden.*"
  else:
    expected_err = ".*Circular dependency.*"

  # validation of this authz file should fail, so no repo access
  svntest.actions.run_and_verify_svn("ls remote folder",
                                     None, expected_err,
                                     'ls',
                                     A_url)

  # Test 3: Group including other group 2 times (issue 2684)
  write_authz_file(sbox, { "/"  : "* = r" },
                         { "groups" : """admins = admin1, admin2
devs1 = @admins, dev1
devs2 = @admins, dev2
users = @devs1, @devs2, user1, user2""" })

  # validation of this authz file should fail, so no repo access
  svntest.actions.run_and_verify_svn("ls remote folder",
                                      ['B/\n', 'C/\n', 'D/\n', 'mu\n'],
                                      [],
                                     'ls',
                                     A_url)
def specific_deny_authz(sbox):
  "verify if specifically denied paths dont sync"

  sbox.build("specific-deny-authz")

  dest_sbox = sbox.clone_dependent()
  build_repos(dest_sbox)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  run_init(dest_sbox.repo_url, sbox.repo_url)

  svntest.main.run_svn(None, "cp",
                       os.path.join(sbox.wc_dir, "A"),
                       os.path.join(sbox.wc_dir, "A_COPY")
                       )
  svntest.main.run_svn(None, "ci", "-mm", sbox.wc_dir)

  write_restrictive_svnserve_conf(sbox.repo_dir)

  # For mod_dav_svn's parent path setup we need per-repos permissions in
  # the authz file...
  if sbox.repo_url.startswith('http'):
    svntest.main.file_write(sbox.authz_file,
                            "[specific-deny-authz:/]\n"
                            "* = r\n"
                            "\n"
                            "[specific-deny-authz:/A]\n"
                            "* = \n"
                            "\n"
                            "[specific-deny-authz:/A_COPY/B/lambda]\n"
                            "* = \n"
                            "\n"
                            "[specific-deny-authz-1:/]\n"
                            "* = rw\n")
  # Otherwise we can just go with the permissions needed for the source
  # repository.
  else:
    svntest.main.file_write(sbox.authz_file,
                            "[/]\n"
                            "* = r\n"
                            "\n"
                            "[/A]\n"
                            "* = \n"
                            "\n"
                            "[/A_COPY/B/lambda]\n"
                            "* = \n")

  run_sync(dest_sbox.repo_url)

  lambda_url = dest_sbox.repo_url + '/A_COPY/B/lambda'

  # this file should have been blocked by authz
  svntest.actions.run_and_verify_svn(None,
                                     [], svntest.verify.AnyOutput,
                                     'cat',
                                     lambda_url)
Esempio n. 26
0
def authz_checkout_and_update_test(sbox):
  "test authz for checkout and update"

  sbox.build(create_wc = False, read_only = True)
  local_dir = sbox.wc_dir

  write_restrictive_svnserve_conf(sbox.repo_dir)

  # 1st part: disable read access on folder A/B, checkout should not
  # download this folder

  # write an authz file with *= on /A/B
  write_authz_file(sbox, { "/": "* = r",
                           "/A/B": "* ="})

  # checkout a working copy, should not dl /A/B
  expected_output = svntest.main.greek_state.copy()
  expected_output.wc_dir = local_dir
  expected_output.tweak(status='A ', contents=None)
  expected_output.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
                         'A/B/E/beta', 'A/B/F')

  expected_wc = svntest.main.greek_state.copy()
  expected_wc.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
                     'A/B/E/beta', 'A/B/F')

  svntest.actions.run_and_verify_checkout(sbox.repo_url, local_dir,
                                          expected_output,
                                          expected_wc)

  # 2nd part: now enable read access

  # write an authz file with *=r on /
  write_authz_file(sbox, { "/": "* = r"})

  # update the working copy, should download /A/B because we now have read
  # access
  expected_output = svntest.wc.State(local_dir, {
    'A/B' : Item(status='A '),
    'A/B/lambda' : Item(status='A '),
    'A/B/E' : Item(status='A '),
    'A/B/E/alpha' : Item(status='A '),
    'A/B/E/beta' : Item(status='A '),
    'A/B/F' : Item(status='A '),
    })

  expected_wc = svntest.main.greek_state
  expected_status = svntest.actions.get_virginal_state(local_dir, 1)

  svntest.actions.run_and_verify_update(local_dir,
                                        expected_output,
                                        expected_wc,
                                        expected_status,
                                        None,
                                        None, None,
                                        None, None, 1)
Esempio n. 27
0
def authz_locking(sbox):
  "test authz for locking"

  sbox.build()

  write_authz_file(sbox, {"/": "", "/A": "jrandom = rw"})
  write_restrictive_svnserve_conf(sbox.repo_dir)

  if sbox.repo_url.startswith('http'):
    expected_err = ".*403 Forbidden.*"
  else:
    expected_err = ".*svn: Authorization failed.*"

  root_url = sbox.repo_url
  wc_dir = sbox.wc_dir
  iota_url = root_url + '/iota'
  iota_path = os.path.join(wc_dir, 'iota')
  A_url = root_url + '/A'
  mu_path = os.path.join(wc_dir, 'A', 'mu')

  # lock a file url, target is readonly: should fail
  svntest.actions.run_and_verify_svn(None,
                                     None, expected_err,
                                     'lock',
                                     '-m', 'lock msg',
                                     iota_url)

  # lock a file path, target is readonly: should fail
  svntest.actions.run_and_verify_svn(None,
                                     None, expected_err,
                                     'lock',
                                     '-m', 'lock msg',
                                     iota_path)

  # Test for issue 2700: we have write access in folder /A, but not in root.
  # Get a lock on /A/mu and try to commit it.

  # lock a file path, target is writeable: should succeed
  svntest.actions.run_and_verify_svn(None,
                                     None, [],
                                     'lock',
                                     '-m', 'lock msg',
                                     mu_path)

  svntest.main.file_append(mu_path, "hi")

  expected_output = svntest.wc.State(wc_dir, {
    'A/mu' : Item(verb='Sending'),
    })

  svntest.actions.run_and_verify_commit(wc_dir,
                                        expected_output,
                                        [],
                                        None,
                                        mu_path)
Esempio n. 28
0
def copy_with_mod_from_unreadable_dir_and_copy(sbox):
    "verify copies with mods from unreadable dirs +copy"

    sbox.build()

    # Make a copy of the B directory.
    svntest.actions.run_and_verify_svn(None, [], "cp", sbox.wc_dir + "/A/B", sbox.wc_dir + "/A/P")

    # Copy a (readable) file into the copied directory.
    svntest.actions.run_and_verify_svn(None, [], "cp", sbox.wc_dir + "/A/D/gamma", sbox.wc_dir + "/A/P/E")

    # Commit the copy-with-modification.
    svntest.actions.run_and_verify_svn(None, [], "ci", sbox.wc_dir, "-m", "log_msg")

    # Lock down the source repository.
    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    dest_sbox.build(create_wc=False, empty=True)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    src_authz = sbox.authz_name()
    dst_authz = dest_sbox.authz_name()
    write_authz_file(
        sbox, None, prefixed_rules={src_authz + ":/": "* = r", src_authz + ":/A/B": "* =", dst_authz + ":/": "* = rw"}
    )

    run_init(dest_sbox.repo_url, sbox.repo_url)

    run_sync(dest_sbox.repo_url)

    expected_out = [
        "Changed paths:\n",
        "   A /A/P\n",
        "   A /A/P/E\n",
        "   A /A/P/E/alpha\n",
        "   A /A/P/E/beta\n",
        "   A /A/P/E/gamma (from /A/D/gamma:1)\n",
        "   A /A/P/F\n",
        "   A /A/P/lambda\n",
        "\n",
        "\n",  # log message is stripped
    ]

    exit_code, out, err = svntest.main.run_svn(None, "log", "-r", "2", "-v", dest_sbox.repo_url)

    if err:
        raise SVNUnexpectedStderr(err)

    svntest.verify.compare_and_display_lines(None, "LOG", expected_out, out[2:12])
Esempio n. 29
0
def authz_svnserve_anon_access_read(sbox):
    "authz issue #2712"

    sbox.build(create_wc=False)
    svntest.main.safe_rmtree(sbox.wc_dir)
    B_path = os.path.join(sbox.wc_dir, 'A', 'B')
    other_B_path = B_path + '_other'
    B_url = sbox.repo_url + '/A/B'
    D_path = os.path.join(sbox.wc_dir, 'A', 'D')
    D_url = sbox.repo_url + '/A/D'

    # We want a svnserve.conf with anon-access = read.
    write_restrictive_svnserve_conf(sbox.repo_dir, "read")

    # Give jrandom read access to /A/B.  Anonymous users can only
    # access /A/D.
    write_authz_file(sbox, {"/A/B": "jrandom = rw", "/A/D": "* = r"})

    # Perform a checkout of /A/B, expecting to see no errors.
    svntest.actions.run_and_verify_svn(None, None, [], 'checkout', B_url,
                                       B_path)

    # Anonymous users should be able to check out /A/D.
    svntest.actions.run_and_verify_svn(None, None, [], 'checkout', D_url,
                                       D_path)

    # Now try a switch.
    svntest.main.safe_rmtree(D_path)
    svntest.actions.run_and_verify_svn(None, None, [], 'switch', D_url, B_path)

    # Check out /A/B with an unknown username, expect error.
    svntest.actions.run_and_verify_svn(
        None, None, ".*Authentication error from server: Username not found.*",
        'checkout', '--non-interactive', '--username', 'losing_user', B_url,
        B_path + '_unsuccessful')

    # Check out a second copy of /A/B, make changes for later merge.
    svntest.actions.run_and_verify_svn(None, None, [], 'checkout', B_url,
                                       other_B_path)
    other_alpha_path = os.path.join(other_B_path, 'E', 'alpha')
    svntest.main.file_append(other_alpha_path, "fish\n")
    svntest.actions.run_and_verify_svn(None, None, [], 'commit', '-m',
                                       'log msg', other_B_path)

    # Now try to merge.  This is an atypical merge, since our "branch"
    # is not really a branch (it's the same URL), but we only care about
    # authz here, not the semantics of the merge.  (Merges had been
    # failing in authz, for the reasons summarized in
    # http://subversion.tigris.org/issues/show_bug.cgi?id=2712#desc13.)
    svntest.actions.run_and_verify_svn(None, None, [], 'merge', '-c', '2',
                                       B_url, B_path)
Esempio n. 30
0
def authz_checkout_and_update_test(sbox):
    "test authz for checkout and update"

    sbox.build(create_wc=False, read_only=True)
    local_dir = sbox.wc_dir

    write_restrictive_svnserve_conf(sbox.repo_dir)

    # 1st part: disable read access on folder A/B, checkout should not
    # download this folder

    # write an authz file with *= on /A/B
    write_authz_file(sbox, {"/": "* = r", "/A/B": "* ="})

    # checkout a working copy, should not dl /A/B
    expected_output = svntest.main.greek_state.copy()
    expected_output.wc_dir = local_dir
    expected_output.tweak(status='A ', contents=None)
    expected_output.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
                           'A/B/E/beta', 'A/B/F')

    expected_wc = svntest.main.greek_state.copy()
    expected_wc.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
                       'A/B/E/beta', 'A/B/F')

    svntest.actions.run_and_verify_checkout(sbox.repo_url, local_dir,
                                            expected_output, expected_wc)

    # 2nd part: now enable read access

    # write an authz file with *=r on /
    write_authz_file(sbox, {"/": "* = r"})

    # update the working copy, should download /A/B because we now have read
    # access
    expected_output = svntest.wc.State(
        local_dir, {
            'A/B': Item(status='A '),
            'A/B/lambda': Item(status='A '),
            'A/B/E': Item(status='A '),
            'A/B/E/alpha': Item(status='A '),
            'A/B/E/beta': Item(status='A '),
            'A/B/F': Item(status='A '),
        })

    expected_wc = svntest.main.greek_state
    expected_status = svntest.actions.get_virginal_state(local_dir, 1)

    svntest.actions.run_and_verify_update(local_dir, expected_output,
                                          expected_wc, expected_status, None,
                                          None, None, None, None, 1)
Esempio n. 31
0
def specific_deny_authz(sbox):
  "verify if specifically denied paths dont sync"

  sbox.build()

  dest_sbox = sbox.clone_dependent()
  dest_sbox.build(create_wc=False, empty=True)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  run_init(dest_sbox.repo_url, sbox.repo_url)

  svntest.main.run_svn(None, "cp",
                       os.path.join(sbox.wc_dir, "A"),
                       os.path.join(sbox.wc_dir, "A_COPY")
                       )
  svntest.main.run_svn(None, "ci", "-mm", sbox.wc_dir)

  write_restrictive_svnserve_conf(sbox.repo_dir)

  # For mod_dav_svn's parent path setup we need per-repos permissions in
  # the authz file...
  if svntest.main.is_ra_type_dav():
    src_authz = sbox.authz_name()
    dst_authz = dest_sbox.authz_name()
    write_authz_file(sbox, None,
                   prefixed_rules = {
                       src_authz + ':/':                '* = r',
                       src_authz + ':/A':               '* =',
                       src_authz + ':/A_COPY/B/lambda': '* =',
                       dst_authz + ':/':                '* = rw',
                       })
  # Otherwise we can just go with the permissions needed for the source
  # repository.
  else:
    write_authz_file(sbox, None,
                   prefixed_rules = {
                       '/':                '* = r',
                       '/A':               '* =',
                       '/A_COPY/B/lambda': '* =',
                       })

  run_sync(dest_sbox.repo_url)

  lambda_url = dest_sbox.repo_url + '/A_COPY/B/lambda'

  # this file should have been blocked by authz
  svntest.actions.run_and_verify_svn([], svntest.verify.AnyOutput,
                                     'cat',
                                     lambda_url)
Esempio n. 32
0
def specific_deny_authz(sbox):
  "verify if specifically denied paths dont sync"

  sbox.build()

  dest_sbox = sbox.clone_dependent()
  dest_sbox.build(create_wc=False, empty=True)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  run_init(dest_sbox.repo_url, sbox.repo_url)

  svntest.main.run_svn(None, "cp",
                       os.path.join(sbox.wc_dir, "A"),
                       os.path.join(sbox.wc_dir, "A_COPY")
                       )
  svntest.main.run_svn(None, "ci", "-mm", sbox.wc_dir)

  write_restrictive_svnserve_conf(sbox.repo_dir)

  # For mod_dav_svn's parent path setup we need per-repos permissions in
  # the authz file...
  if svntest.main.is_ra_type_dav():
    src_authz = sbox.authz_name()
    dst_authz = dest_sbox.authz_name()
    write_authz_file(sbox, None,
                   prefixed_rules = {
                       src_authz + ':/':                '* = r',
                       src_authz + ':/A':               '* =',
                       src_authz + ':/A_COPY/B/lambda': '* =',
                       dst_authz + ':/':                '* = rw',
                       })
  # Otherwise we can just go with the permissions needed for the source
  # repository.
  else:
    write_authz_file(sbox, None,
                   prefixed_rules = {
                       '/':                '* = r',
                       '/A':               '* =',
                       '/A_COPY/B/lambda': '* =',
                       })

  run_sync(dest_sbox.repo_url)

  lambda_url = dest_sbox.repo_url + '/A_COPY/B/lambda'

  # this file should have been blocked by authz
  svntest.actions.run_and_verify_svn([], svntest.verify.AnyOutput,
                                     'cat',
                                     lambda_url)
Esempio n. 33
0
def authz_switch_to_directory(sbox):
  "switched to directory, no read access on parents"

  sbox.build(read_only = True)

  write_authz_file(sbox, {"/": "*=rw", "/A/B": "*=", "/A/B/E": "jrandom = rw"})

  write_restrictive_svnserve_conf(sbox.repo_dir)

  wc_dir = sbox.wc_dir
  mu_path = os.path.join(wc_dir, 'A', 'mu')
  F_path = os.path.join(wc_dir, 'A', 'B', 'F')
  G_path = os.path.join(wc_dir, 'A', 'D', 'G')

  # Switch /A/B/E to /A/B/F.
  svntest.main.run_svn(None, 'switch', sbox.repo_url + "/A/B/E", G_path)
Esempio n. 34
0
def broken_authz_file(sbox):
    "broken authz files cause errors"

    sbox.build(create_wc=False)

    # No characters but 'r', 'w', and whitespace are allowed as a value
    # in an authz rule.
    write_authz_file(sbox,
                     {"/": "jrandom = rw  # End-line comments disallowed"})

    write_restrictive_svnserve_conf(sbox.repo_dir)

    out, err = svntest.main.run_svn(1, "delete", sbox.repo_url + "/A", "-m",
                                    "a log message")
    if out:
        raise svntest.verify.SVNUnexpectedStdout(out)
    if not err:
        raise svntest.verify.SVNUnexpectedStderr("Missing stderr")
Esempio n. 35
0
def broken_authz_file(sbox):
  "broken authz files cause errors"

  sbox.build(create_wc = False)

  # No characters but 'r', 'w', and whitespace are allowed as a value
  # in an authz rule.
  write_authz_file(sbox, {"/": "jrandom = rw  # End-line comments disallowed"})

  write_restrictive_svnserve_conf(sbox.repo_dir)

  out, err = svntest.main.run_svn(1,
                                  "delete",
                                  sbox.repo_url + "/A",
                                  "-m", "a log message");
  if out:
    raise svntest.verify.SVNUnexpectedStdout(out)
  if not err:
    raise svntest.verify.SVNUnexpectedStderr("Missing stderr")
Esempio n. 36
0
def authz_locking(sbox):
    "test authz for locking"

    sbox.build()

    write_authz_file(sbox, {"/": "", "/A": "jrandom = rw"})
    write_restrictive_svnserve_conf(sbox.repo_dir)

    if sbox.repo_url.startswith('http'):
        expected_err = ".*403 Forbidden.*"
    else:
        expected_err = ".*svn: Authorization failed.*"

    root_url = sbox.repo_url
    wc_dir = sbox.wc_dir
    iota_url = root_url + '/iota'
    iota_path = os.path.join(wc_dir, 'iota')
    A_url = root_url + '/A'
    mu_path = os.path.join(wc_dir, 'A', 'mu')

    # lock a file url, target is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'lock', '-m',
                                       'lock msg', iota_url)

    # lock a file path, target is readonly: should fail
    svntest.actions.run_and_verify_svn(None, None, expected_err, 'lock', '-m',
                                       'lock msg', iota_path)

    # Test for issue 2700: we have write access in folder /A, but not in root.
    # Get a lock on /A/mu and try to commit it.

    # lock a file path, target is writeable: should succeed
    svntest.actions.run_and_verify_svn(None, None, [], 'lock', '-m',
                                       'lock msg', mu_path)

    svntest.main.file_append(mu_path, "hi")

    expected_output = svntest.wc.State(wc_dir, {
        'A/mu': Item(verb='Sending'),
    })

    svntest.actions.run_and_verify_commit(wc_dir, expected_output, [], None,
                                          mu_path)
Esempio n. 37
0
def authz_switch_to_directory(sbox):
    "switched to directory, no read access on parents"

    sbox.build(read_only=True)

    write_authz_file(sbox, {
        "/": "*=rw",
        "/A/B": "*=",
        "/A/B/E": "jrandom = rw"
    })

    write_restrictive_svnserve_conf(sbox.repo_dir)

    wc_dir = sbox.wc_dir
    mu_path = os.path.join(wc_dir, 'A', 'mu')
    F_path = os.path.join(wc_dir, 'A', 'B', 'F')
    G_path = os.path.join(wc_dir, 'A', 'D', 'G')

    # Switch /A/B/E to /A/B/F.
    svntest.main.run_svn(None, 'switch', sbox.repo_url + "/A/B/E", G_path)
Esempio n. 38
0
def basic_authz(sbox):
  "verify that unreadable content is not synced"

  sbox.build(create_wc = False)

  write_restrictive_svnserve_conf(sbox.repo_dir)

  dest_sbox = sbox.clone_dependent()
  build_repos(dest_sbox)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  run_init(dest_sbox.repo_url, sbox.repo_url)

  args = tuple(s.authz_name() for s in [sbox, sbox, dest_sbox])
  svntest.main.file_write(sbox.authz_file,
                          "[%s:/]\n"
                          "* = r\n"
                          "\n"
                          "[%s:/A/B]\n"
                          "* = \n"
                          "\n"
                          "[%s:/]\n"
                          "* = rw\n" % args)

  run_sync(dest_sbox.repo_url)

  lambda_url = dest_sbox.repo_url + '/A/B/lambda'
  iota_url = dest_sbox.repo_url + '/iota'

  # this file should have been blocked by authz
  svntest.actions.run_and_verify_svn(None,
                                     [], svntest.verify.AnyOutput,
                                     'cat',
                                     lambda_url)
  # this file should have been synced
  svntest.actions.run_and_verify_svn(None,
                                     svntest.verify.AnyOutput, [],
                                     'cat',
                                     iota_url)
Esempio n. 39
0
def authz_checkout_test(sbox):
  "test authz for checkout"

  sbox.build(create_wc = False, read_only = True)
  local_dir = sbox.wc_dir

  write_restrictive_svnserve_conf(sbox.repo_dir)

  # 1st part: disable all read access, checkout should fail

  # write an authz file with *= on /
  if sbox.repo_url.startswith('http'):
    expected_err = ".*403 Forbidden.*"
  else:
    expected_err = ".*svn: Authorization failed.*"

  write_authz_file(sbox, { "/": "* ="})

  # checkout a working copy, should fail
  svntest.actions.run_and_verify_svn(None, None, expected_err,
                                     'co', sbox.repo_url, local_dir)

  # 2nd part: now enable read access

  write_authz_file(sbox, { "/": "* = r"})

  # checkout a working copy, should succeed because we have read access
  expected_output = svntest.main.greek_state.copy()
  expected_output.wc_dir = local_dir
  expected_output.tweak(status='A ', contents=None)

  expected_wc = svntest.main.greek_state

  svntest.actions.run_and_verify_checkout(sbox.repo_url,
                          local_dir,
                          expected_output,
                          expected_wc)
Esempio n. 40
0
def authz_access_required_at_repo_root2(sbox):
  "more authz issue #3242 - update to renamed file"

  sbox.build(create_wc = False)
  root_url = sbox.repo_url

  # Now we get all restrictive.
  write_authz_file(sbox, {'/': '* =',
                          '/A': 'jrandom = rw'})
  write_restrictive_svnserve_conf(sbox.repo_dir)

  # Rename a file.
  svntest.main.run_svn(None, 'mv',
                       '-m', 'rename file in readable writable space',
                       root_url + '/A/B/E/alpha',
                       root_url + '/A/B/E/alpha-renamed')
  
  # Check out original greek sub tree below /A/B/E 
  # and update it to the above rename.
  wc_dir = sbox.add_wc_path('ABE')
  os.mkdir(wc_dir)
  svntest.main.run_svn(None, 'co', '-r', '1', root_url + '/A/B/E', wc_dir)
  svntest.main.run_svn(None, 'up', wc_dir)

  # Rename a directory.
  svntest.main.run_svn(None, 'mv',
                       '-m', 'rename diretory in readable writable space',
                       root_url + '/A/D/H',
                       root_url + '/A/D/a g e')
  
  # Check out original greek sub tree below /A/D
  # and update it to the above rename.
  wc_dir = sbox.add_wc_path('AD')
  os.mkdir(wc_dir)
  svntest.main.run_svn(None, 'co', '-r', '1', root_url + '/A/D', wc_dir)
  svntest.main.run_svn(None, 'up', wc_dir)
Esempio n. 41
0
def authz_open_root(sbox):
    "authz issue #2486 - open root"

    sbox.build()

    write_authz_file(sbox, {"/": "", "/A": "jrandom = rw"})

    write_restrictive_svnserve_conf(sbox.repo_dir)

    # we have write access in folder /A, but not in root. Test on too
    # restrictive access needed in open_root by modifying a file in /A
    wc_dir = sbox.wc_dir

    mu_path = os.path.join(wc_dir, 'A', 'mu')
    svntest.main.file_append(mu_path, "hi")

    # Create expected output tree.
    expected_output = svntest.wc.State(wc_dir, {
        'A/mu': Item(verb='Sending'),
    })

    # Commit the one file.
    svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
                                          mu_path)
Esempio n. 42
0
def copy_with_mod_from_unreadable_dir(sbox):
    "verify copies with mods from unreadable dirs"

    sbox.build()

    # Make a copy of the B directory.
    svntest.actions.run_and_verify_svn(None, [], 'cp', sbox.wc_dir + '/A/B',
                                       sbox.wc_dir + '/A/P')

    # Set a property inside the copied directory.
    svntest.actions.run_and_verify_svn(None, [], 'pset', 'foo', 'bar',
                                       sbox.wc_dir + '/A/P/lambda')

    # Add a new directory and file inside the copied directory.
    svntest.actions.run_and_verify_svn(None, [], 'mkdir',
                                       sbox.wc_dir + '/A/P/NEW-DIR')

    svntest.main.file_append(sbox.wc_dir + '/A/P/E/new-file', "bla bla")
    svntest.main.run_svn(None, 'add', sbox.wc_dir + '/A/P/E/new-file')

    # Delete a file inside the copied directory.
    svntest.actions.run_and_verify_svn(None, [], 'rm',
                                       sbox.wc_dir + '/A/P/E/beta')

    # Commit the copy-with-modification.
    svntest.actions.run_and_verify_svn(None, [], 'ci', sbox.wc_dir, '-m',
                                       'log_msg')

    # Lock down the source repository.
    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    dest_sbox.build(create_wc=False, empty=True)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    src_authz = sbox.authz_name()
    dst_authz = dest_sbox.authz_name()
    write_authz_file(sbox,
                     None,
                     prefixed_rules={
                         src_authz + ':/': '* = r',
                         src_authz + ':/A/B': '* =',
                         dst_authz + ':/': '* = rw',
                     })

    run_init(dest_sbox.repo_url, sbox.repo_url)

    run_sync(dest_sbox.repo_url)

    expected_out = [
        'Changed paths:\n',
        '   A /A/P\n',
        '   A /A/P/E\n',
        '   A /A/P/E/alpha\n',
        '   A /A/P/E/new-file\n',
        '   A /A/P/F\n',
        '   A /A/P/NEW-DIR\n',
        '   A /A/P/lambda\n',
        '\n',
        '\n',  # log message is stripped
    ]

    exit_code, out, err = svntest.main.run_svn(None, 'log', '-r', '2', '-v',
                                               dest_sbox.repo_url)

    if err:
        raise SVNUnexpectedStderr(err)

    svntest.verify.compare_and_display_lines(None, 'LOG', expected_out,
                                             out[2:12])

    svntest.actions.run_and_verify_svn(['bar\n'], [], 'pget', 'foo',
                                       dest_sbox.repo_url + '/A/P/lambda')
Esempio n. 43
0
def mergeinfo_and_skipped_paths(sbox):
  "skipped paths get overriding mergeinfo"

  # Test that we override the mergeinfo for child paths which weren't
  # actually merged because they were skipped.
  #
  # This test covers paths skipped because:
  #
  #   1) The source of a merge is inaccessible due to authz restrictions.
  #   2) Destination of merge is inaccessible due to authz restrictions.
  #   3) Source *and* destination of merge is inaccessible due to authz
  #      restrictions.

  sbox.build()
  wc_dir = sbox.wc_dir
  wc_disk, wc_status = set_up_branch(sbox, False, 3)

  # Create a restrictive authz where part of the merge source and part
  # of the target are inaccesible.
  write_restrictive_svnserve_conf(sbox.repo_dir)
  write_authz_file(sbox, {"/"               : svntest.main.wc_author +"=rw",
                          # Make a directory in the merge source inaccessible.
                          "/A/B/E"            : svntest.main.wc_author + "=",
                          # Make a file and dir in the merge destination
                          # inaccessible.
                          "/A_COPY_2/D/H/psi" : svntest.main.wc_author + "=",
                          "/A_COPY_2/D/G" : svntest.main.wc_author + "=",
                          # Make the source and destination inaccessible.
                          "/A_COPY_3/B/E"     : svntest.main.wc_author + "=",
                          })

  # Checkout just the branch under the newly restricted authz.
  wc_restricted = sbox.add_wc_path('restricted')
  svntest.actions.run_and_verify_svn(None, None, [], 'checkout',
                                     sbox.repo_url,
                                     wc_restricted)

  # Some paths we'll use in the second WC.
  A_COPY_path = os.path.join(wc_restricted, "A_COPY")
  A_COPY_2_path = os.path.join(wc_restricted, "A_COPY_2")
  A_COPY_2_H_path = os.path.join(wc_restricted, "A_COPY_2", "D", "H")
  A_COPY_3_path = os.path.join(wc_restricted, "A_COPY_3")
  omega_path = os.path.join(wc_restricted, "A_COPY", "D", "H", "omega")
  zeta_path = sbox.ospath("A/D/H/zeta")

  # Merge r4:8 into the restricted WC's A_COPY.
  #
  # We expect A_COPY/B/E to be skipped because we can't access the source
  # and A_COPY/D/H/omega because it is missing.  Since we have A_COPY/B/E
  # we should override it's inherited mergeinfo, giving it just what it
  # inherited from A_COPY before the merge.
  expected_output = wc.State(A_COPY_path, {
    'D/G/rho'   : Item(status='U '),
    'D/H/psi'   : Item(status='U '),
    'D/H/omega' : Item(status='U '),
    })
  expected_mergeinfo_output = wc.State(A_COPY_path, {
    ''          : Item(status=' U'),
    'B/E'       : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_path, {
    })
  expected_status = wc.State(A_COPY_path, {
    ''          : Item(status=' M', wc_rev=8),
    'D/H/chi'   : Item(status='  ', wc_rev=8),
    'D/H/psi'   : Item(status='M ', wc_rev=8),
    'D/H/omega' : Item(status='M ', wc_rev=8),
    'D/H'       : Item(status='  ', wc_rev=8),
    'D/G/pi'    : Item(status='  ', wc_rev=8),
    'D/G/rho'   : Item(status='M ', wc_rev=8),
    'D/G/tau'   : Item(status='  ', wc_rev=8),
    'D/G'       : Item(status='  ', wc_rev=8),
    'D/gamma'   : Item(status='  ', wc_rev=8),
    'D'         : Item(status='  ', wc_rev=8),
    'B/lambda'  : Item(status='  ', wc_rev=8),
    'B/E'       : Item(status=' M', wc_rev=8),
    'B/E/alpha' : Item(status='  ', wc_rev=8),
    'B/E/beta'  : Item(status='  ', wc_rev=8),
    'B/F'       : Item(status='  ', wc_rev=8),
    'B'         : Item(status='  ', wc_rev=8),
    'mu'        : Item(status='  ', wc_rev=8),
    'C'         : Item(status='  ', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:5-8'}),
    'D/H/psi'   : Item("New content"),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
    'D/H/omega' : Item("New content"),
    'D/H'       : Item(),
    'D/G/pi'    : Item("This is the file 'pi'.\n"),
    'D/G/rho'   : Item("New content"),
    'D/G/tau'   : Item("This is the file 'tau'.\n"),
    'D/G'       : Item(),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D'         : Item(),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/E'       : Item(props={SVN_PROP_MERGEINFO : ''}),
    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
    'B/E/beta'  : Item("This is the file 'beta'.\n"),
    'B/F'       : Item(),
    'B'         : Item(),
    'mu'        : Item("This is the file 'mu'.\n"),
    'C'         : Item(),
    })
  expected_skip = wc.State(A_COPY_path, {
    'B/E'       : Item(verb='Skipped missing target'),
    })
  svntest.actions.run_and_verify_merge(A_COPY_path, '4', '8',
                                       sbox.repo_url + '/A', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1)

  # Merge r4:8 into the restricted WC's A_COPY_2.
  #
  # As before we expect A_COPY_2/B/E to be skipped because we can't access the
  # source but now the destination paths A_COPY_2/D/G, A_COPY_2/D/G/rho, and
  # A_COPY_2/D/H/psi should also be skipped because our test user doesn't have
  # access.
  #
  # After the merge the parents of the missing dest paths, A_COPY_2/D and
  # A_COPY_2/D/H get non-inheritable mergeinfo.  Those parents' children that
  # *are* present and are affected by the merge, only A_COPY_2/D/H/omega in
  # this case, get their own mergeinfo.  Note that A_COPY_2/D/H is both the
  # parent of a missing child and the sibling of missing child, but the former
  # always takes precedence in terms of getting *non*-inheritable mergeinfo.
  expected_output = wc.State(A_COPY_2_path, {
    'D/H/omega' : Item(status='U '),
    # Below the skip
    'D/G/rho'   : Item(status='  ', treeconflict='U'),
    })
  expected_mergeinfo_output = wc.State(A_COPY_2_path, {
    ''          : Item(status=' U'),
    'D'         : Item(status=' U'),
    'D/H'       : Item(status=' U'),
    'D/H/omega' : Item(status=' U'),
    'B/E'       : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_2_path, {
    })
  expected_status = wc.State(A_COPY_2_path, {
    ''          : Item(status=' M', wc_rev=8),
    'D/H/chi'   : Item(status='  ', wc_rev=8),
    'D/H/omega' : Item(status='MM', wc_rev=8),
    'D/H'       : Item(status=' M', wc_rev=8),
    'D/gamma'   : Item(status='  ', wc_rev=8),
    'D'         : Item(status=' M', wc_rev=8),
    'B/lambda'  : Item(status='  ', wc_rev=8),
    'B/E'       : Item(status=' M', wc_rev=8),
    'B/E/alpha' : Item(status='  ', wc_rev=8),
    'B/E/beta'  : Item(status='  ', wc_rev=8),
    'B/F'       : Item(status='  ', wc_rev=8),
    'B'         : Item(status='  ', wc_rev=8),
    'mu'        : Item(status='  ', wc_rev=8),
    'C'         : Item(status='  ', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:5-8'}),
    'D/H/omega' : Item("New content",
                       props={SVN_PROP_MERGEINFO : '/A/D/H/omega:5-8'}),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
    'D/H'       : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:5-8*'}),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D'         : Item(props={SVN_PROP_MERGEINFO : '/A/D:5-8*'}),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/E'       : Item(props={SVN_PROP_MERGEINFO : ''}),
    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
    'B/E/beta'  : Item("This is the file 'beta'.\n"),
    'B/F'       : Item(),
    'B'         : Item(),
    'mu'        : Item("This is the file 'mu'.\n"),
    'C'         : Item(),
    })
  expected_skip = wc.State(A_COPY_2_path, {
    'B/E'     : Item(verb='Skipped missing target'),
    'D/G'     : Item(verb='Skipped missing target'),
    'D/H/psi' : Item(verb='Skipped missing target'),
    })
  svntest.actions.run_and_verify_merge(A_COPY_2_path, '4', '8',
                                       sbox.repo_url + '/A', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1, 0)

  # Merge r5:7 into the restricted WC's A_COPY_3.
  #
  # Again A_COPY_3/B/E should be skipped, but because we can't access the
  # source *or* the destination we expect its parent A_COPY_3/B to get
  # non-inheritable mergeinfo.  A_COPY_3B's two existing siblings,
  # A_COPY_3/B/F and A_COPY_3/B/lambda are untouched by the merge so
  # neither gets any mergeinfo recorded.
  expected_output = wc.State(A_COPY_3_path, {
    'D/G/rho' : Item(status='U '),
    })
  expected_mergeinfo_output = wc.State(A_COPY_3_path, {
    ''  : Item(status=' U'),
    'B' : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_3_path, {
    })
  expected_status = wc.State(A_COPY_3_path, {
    ''          : Item(status=' M', wc_rev=8),
    'D/H/chi'   : Item(status='  ', wc_rev=8),
    'D/H/omega' : Item(status='  ', wc_rev=8),
    'D/H/psi'   : Item(status='  ', wc_rev=8),
    'D/H'       : Item(status='  ', wc_rev=8),
    'D/gamma'   : Item(status='  ', wc_rev=8),
    'D'         : Item(status='  ', wc_rev=8),
    'D/G'       : Item(status='  ', wc_rev=8),
    'D/G/pi'    : Item(status='  ', wc_rev=8),
    'D/G/rho'   : Item(status='M ', wc_rev=8),
    'D/G/tau'   : Item(status='  ', wc_rev=8),
    'B/lambda'  : Item(status='  ', wc_rev=8),
    'B/F'       : Item(status='  ', wc_rev=8),
    'B'         : Item(status=' M', wc_rev=8),
    'mu'        : Item(status='  ', wc_rev=8),
    'C'         : Item(status='  ', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:6-7'}),
    'D/H/omega' : Item("This is the file 'omega'.\n"),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
    'D/H/psi'   : Item("This is the file 'psi'.\n"),
    'D/H'       : Item(),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D'         : Item(),
    'D/G'       : Item(),
    'D/G/pi'    : Item("This is the file 'pi'.\n"),
    'D/G/rho'   : Item("New content"),
    'D/G/tau'   : Item("This is the file 'tau'.\n"),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/F'       : Item(),
    'B'         : Item(props={SVN_PROP_MERGEINFO : '/A/B:6-7*'}),
    'mu'        : Item("This is the file 'mu'.\n"),
    'C'         : Item(),
    })
  expected_skip = wc.State(A_COPY_3_path,
                           {'B/E' : Item(verb='Skipped missing target')})
  svntest.actions.run_and_verify_merge(A_COPY_3_path, '5', '7',
                                       sbox.repo_url + '/A', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1, 0)
  svntest.actions.run_and_verify_svn(None, None, [], 'revert', '--recursive',
                                     wc_restricted)

  # Test issue #2997.  If a merge requires two separate editor drives and the
  # first is non-operative we should still update the mergeinfo to reflect
  # this.
  #
  # Merge -c5 -c8 to the restricted WC's A_COPY_2/D/H.  r5 gets merged first
  # but is a no-op, r8 get's merged next and is operative so the mergeinfo
  # should be updated on the merge target to reflect both merges.
  expected_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status='U '),
    })
  expected_elision_output = wc.State(A_COPY_2_H_path, {
    })
  expected_status = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' M', wc_rev=8),
    'chi'   : Item(status='  ', wc_rev=8),
    'omega' : Item(status='MM', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:5*,8*'}),
    'omega' : Item("New content",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/omega:8'}),
    'chi'   : Item("This is the file 'chi'.\n"),
    })
  expected_skip = wc.State(A_COPY_2_H_path, {
    'psi'   : Item(verb='Skipped missing target'),
    })
  # Note we don't bother checking expected mergeinfo output because the
  # multiple merges being performed here, -c5 and -c8, will result in
  # first ' U' and then ' G' mergeinfo notifications.  Our expected
  # tree structures can't handle checking for multiple values for the
  # same key.
  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '4', '5',
                                       sbox.repo_url + '/A/D/H', None,
                                       expected_output,
                                       None, # expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1, 0, '-c5', '-c8',
                                       A_COPY_2_H_path)

  # Test issue #2829 'Improve handling for skipped paths encountered
  # during a merge'

  # Revert previous changes to restricted WC
  svntest.actions.run_and_verify_svn(None, None, [], 'revert', '--recursive',
                                     wc_restricted)
  # Add new path 'A/D/H/zeta'
  svntest.main.file_write(zeta_path, "This is the file 'zeta'.\n")
  svntest.actions.run_and_verify_svn(None, None, [], 'add', zeta_path)
  expected_output = wc.State(wc_dir, {'A/D/H/zeta' : Item(verb='Adding')})
  wc_status.add({'A/D/H/zeta' : Item(status='  ', wc_rev=9)})
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        wc_status, None, wc_dir)

  # Merge -r7:9 to the restricted WC's A_COPY_2/D/H.
  #
  # r9 adds a path, 'A_COPY_2/D/H/zeta', which has a missing sibling 'psi',
  # but since 'psi' is untouched by the merge it isn't skipped, and since it
  # isn't skipped, its parent 'A_COPY_2/D/H' won't get non-inheritable
  # mergeinfo set on it to describe the merge, so none of the parent's
  # children will get explicit mergeinfo -- see issue #4056.
  expected_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status='U '),
    'zeta'  : Item(status='A '),
    })
  expected_mergeinfo_output = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' U'),
    'omega' : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status=' U'),
    })
  expected_status = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' M', wc_rev=8),
    'chi'   : Item(status='  ', wc_rev=8),
    'omega' : Item(status='M ', wc_rev=8),
    'zeta'  : Item(status='A ', copied='+', wc_rev='-'),
    })
  expected_disk = wc.State('', {
    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:8-9'}),
    'omega' : Item("New content"),
    'chi'   : Item("This is the file 'chi'.\n"),
    'zeta'  : Item("This is the file 'zeta'.\n"),
    })
  expected_skip = wc.State(A_COPY_2_H_path, {})
  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '7', '9',
                                       sbox.repo_url + '/A/D/H', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1, 0)

  # Merge -r4:9 to the restricted WC's A_COPY_2/D/H.
  #
  # r9 adds a path, 'A_COPY_2/D/H/zeta', which has a parent with
  # non-inheritable mergeinfo (due to the fact 'A_COPY_2/D/H/psi' is missing
  # and skipped). 'A_COPY_2/D/H/zeta' must therefore get its own explicit
  # mergeinfo from this merge.
  svntest.actions.run_and_verify_svn(None, None, [], 'revert', '--recursive',
                                     wc_restricted)
  expected_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status='U '),
    'zeta'  : Item(status='A '),
    })
  expected_mergeinfo_output = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' U'),
    'omega' : Item(status=' U'),
    'zeta'  : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_2_H_path, {
    })
  expected_status = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' M', wc_rev=8),
    'chi'   : Item(status='  ', wc_rev=8),
    'omega' : Item(status='MM', wc_rev=8),
    'zeta'  : Item(status='A ', copied='+', wc_rev='-'),
    })
  expected_disk = wc.State('', {
    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:5-9*'}),
    'omega' : Item("New content",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/omega:5-9'}),
    'chi'   : Item("This is the file 'chi'.\n"),
    'zeta'  : Item("This is the file 'zeta'.\n",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/zeta:9'}),
    })
  expected_skip = wc.State(A_COPY_2_H_path, {
    'psi' : Item(verb='Skipped missing target'),
    })
  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '4', '9',
                                       sbox.repo_url + '/A/D/H', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1, 0)
Esempio n. 44
0
def reintegrate_fails_if_no_root_access(sbox):
  "reintegrate fails if no root access"

  # If a user is authorized to a reintegrate source and target, they
  # should be able to reintegrate, regardless of what authorization
  # they have to parents of the source and target.
  #
  # See http://subversion.tigris.org/issues/show_bug.cgi?id=3242#desc78

  # Some paths we'll care about
  wc_dir = sbox.wc_dir
  A_path          = sbox.ospath('A')
  A_COPY_path     = sbox.ospath('A_COPY')
  beta_COPY_path  = sbox.ospath('A_COPY/B/E/beta')
  rho_COPY_path   = sbox.ospath('A_COPY/D/G/rho')
  omega_COPY_path = sbox.ospath('A_COPY/D/H/omega')
  psi_COPY_path   = sbox.ospath('A_COPY/D/H/psi')

  # Copy A@1 to A_COPY in r2, and then make some changes to A in r3-6.
  sbox.build()
  wc_dir = sbox.wc_dir
  expected_disk, expected_status = set_up_branch(sbox)

  # Make a change on the branch, to A_COPY/mu, commit in r7.
  svntest.main.file_write(sbox.ospath("A_COPY/mu"),
                          "Changed on the branch.")
  expected_output = wc.State(wc_dir, {'A_COPY/mu' : Item(verb='Sending')})
  expected_status.tweak('A_COPY/mu', wc_rev=7)
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        expected_status, None, wc_dir)
  expected_disk.tweak('A_COPY/mu', contents='Changed on the branch.')

  # Update the WC.
  svntest.main.run_svn(None, 'up', wc_dir)


  # Sync A_COPY with A.
  expected_output = expected_merge_output([[2,7]],
                                          ['U    ' + beta_COPY_path  + '\n',
                                           'U    ' + rho_COPY_path   + '\n',
                                           'U    ' + omega_COPY_path + '\n',
                                           'U    ' + psi_COPY_path   + '\n',
                                           # Mergeinfo notification
                                           ' U   ' + A_COPY_path     + '\n'])
  svntest.actions.run_and_verify_svn(None, expected_output, [], 'merge',
                                     sbox.repo_url + '/A', A_COPY_path)
  svntest.main.run_svn(None, 'ci', '-m', 'synch A_COPY with A', wc_dir)

  # Update so we are ready for reintegrate.
  svntest.main.run_svn(None, 'up', wc_dir)

  # Change authz file so everybody has access to everything but the root.
  if is_ra_type_svn() or is_ra_type_dav():
    write_restrictive_svnserve_conf(sbox.repo_dir)
    write_authz_file(sbox, {"/"       : "* =",
                            "/A"      : "* = rw",
                            "/A_COPY" : "* = rw",
                            "/iota"   : "* = rw"})

  # Now reintegrate A_COPY back to A.  The lack of access to the root of the
  # repository shouldn't be a problem.
  expected_output = wc.State(A_path, {
    'mu'           : Item(status='U '),
    })
  expected_mergeinfo_output = wc.State(A_path, {
    '' : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_path, {
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A_COPY:2-8'}),
    'B'         : Item(),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/E'       : Item(),
    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
    'B/E/beta'  : Item("New content"),
    'B/F'       : Item(),
    'mu'        : Item("Changed on the branch."),
    'C'         : Item(),
    'D'         : Item(),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D/G'       : Item(),
    'D/G/pi'    : Item("This is the file 'pi'.\n"),
    'D/G/rho'   : Item("New content"),
    'D/G/tau'   : Item("This is the file 'tau'.\n"),
    'D/H'       : Item(),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
    'D/H/omega' : Item("New content"),
    'D/H/psi'   : Item("New content"),
  })
  expected_status = wc.State(A_path, {
    "B"            : Item(status='  ', wc_rev=8),
    "B/lambda"     : Item(status='  ', wc_rev=8),
    "B/E"          : Item(status='  ', wc_rev=8),
    "B/E/alpha"    : Item(status='  ', wc_rev=8),
    "B/E/beta"     : Item(status='  ', wc_rev=8),
    "B/F"          : Item(status='  ', wc_rev=8),
    "mu"           : Item(status='M ', wc_rev=8),
    "C"            : Item(status='  ', wc_rev=8),
    "D"            : Item(status='  ', wc_rev=8),
    "D/gamma"      : Item(status='  ', wc_rev=8),
    "D/G"          : Item(status='  ', wc_rev=8),
    "D/G/pi"       : Item(status='  ', wc_rev=8),
    "D/G/rho"      : Item(status='  ', wc_rev=8),
    "D/G/tau"      : Item(status='  ', wc_rev=8),
    "D/H"          : Item(status='  ', wc_rev=8),
    "D/H/chi"      : Item(status='  ', wc_rev=8),
    "D/H/omega"    : Item(status='  ', wc_rev=8),
    "D/H/psi"      : Item(status='  ', wc_rev=8),
    ""             : Item(status=' M', wc_rev=8),
  })
  expected_skip = wc.State(A_path, {})
  svntest.actions.run_and_verify_merge(A_path, None, None,
                                       sbox.repo_url + '/A_COPY', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, True, True,
                                       '--reintegrate', A_path)
Esempio n. 45
0
def copy_from_unreadable_dir(sbox):
  "verify that copies from unreadable dirs work"

  sbox.build()

  B_url = sbox.repo_url + '/A/B'
  P_url = sbox.repo_url + '/A/P'

  # Set a property on the directory we're going to copy, and a file in it, to
  # confirm that they're transmitted when we later sync the copied directory
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'pset',
                                     'foo',
                                     'bar',
                                     sbox.wc_dir + '/A/B/lambda')

  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'pset',
                                     'baz',
                                     'zot',
                                     sbox.wc_dir + '/A/B')

  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'ci',
                                     sbox.wc_dir + '/A/B',
                                     '-m', 'log_msg')

  # Now copy that directory so we'll see it in our synced copy
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'cp',
                                     B_url,
                                     P_url,
                                     '-m', 'Copy B to P')

  write_restrictive_svnserve_conf(sbox.repo_dir)

  dest_sbox = sbox.clone_dependent()
  dest_sbox.build(create_wc=False, empty=True)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  src_authz = sbox.authz_name()
  dst_authz = dest_sbox.authz_name()
  write_authz_file(sbox, None,
                   prefixed_rules = {
                       src_authz + ':/':    '* = r',
                       src_authz + ':/A/B': '* =',
                       dst_authz + ':/':    '* = rw',
                       })

  run_init(dest_sbox.repo_url, sbox.repo_url)

  run_sync(dest_sbox.repo_url)

  expected_out = [
    'Changed paths:\n',
    '   A /A/P\n',
    '   A /A/P/E\n',
    '   A /A/P/E/alpha\n',
    '   A /A/P/E/beta\n',
    '   A /A/P/F\n',
    '   A /A/P/lambda\n',
    '\n',
    '\n', # log message is stripped
  ]

  exit_code, out, err = svntest.main.run_svn(None,
                                             'log',
                                             '-r', '3',
                                             '-v',
                                             dest_sbox.repo_url)

  if err:
    raise SVNUnexpectedStderr(err)

  svntest.verify.compare_and_display_lines(None,
                                           'LOG',
                                           expected_out,
                                           out[2:11])

  svntest.actions.run_and_verify_svn(['bar\n'],
                                     [],
                                     'pget',
                                     'foo',
                                     dest_sbox.repo_url + '/A/P/lambda')

  svntest.actions.run_and_verify_svn(['zot\n'],
                                     [],
                                     'pget',
                                     'baz',
                                     dest_sbox.repo_url + '/A/P')
Esempio n. 46
0
def authz_svnserve_anon_access_read(sbox):
  "authz issue #2712"

  sbox.build(create_wc = False)
  svntest.main.safe_rmtree(sbox.wc_dir)
  B_path = os.path.join(sbox.wc_dir, 'A', 'B')
  other_B_path = B_path + '_other'
  B_url = sbox.repo_url + '/A/B'
  D_path = os.path.join(sbox.wc_dir, 'A', 'D')
  D_url = sbox.repo_url + '/A/D'

  # We want a svnserve.conf with anon-access = read.
  write_restrictive_svnserve_conf(sbox.repo_dir, "read")

  # Give jrandom read access to /A/B.  Anonymous users can only
  # access /A/D.
  write_authz_file(sbox, { "/A/B" : "jrandom = rw",
                           "/A/D" : "* = r" })

  # Perform a checkout of /A/B, expecting to see no errors.
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'checkout',
                                     B_url, B_path)

  # Anonymous users should be able to check out /A/D.
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'checkout',
                                     D_url, D_path)

  # Now try a switch.
  svntest.main.safe_rmtree(D_path)
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'switch', D_url, B_path)

  # Check out /A/B with an unknown username, expect error.
  svntest.actions.run_and_verify_svn(
    None, None,
    ".*Authentication error from server: Username not found.*",
    'checkout',
    '--non-interactive',
    '--username', 'losing_user',
    B_url, B_path + '_unsuccessful')

  # Check out a second copy of /A/B, make changes for later merge.
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'checkout',
                                     B_url, other_B_path)
  other_alpha_path = os.path.join(other_B_path, 'E', 'alpha')
  svntest.main.file_append(other_alpha_path, "fish\n")
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'commit', '-m', 'log msg',
                                     other_B_path)

  # Now try to merge.  This is an atypical merge, since our "branch"
  # is not really a branch (it's the same URL), but we only care about
  # authz here, not the semantics of the merge.  (Merges had been
  # failing in authz, for the reasons summarized in
  # http://subversion.tigris.org/issues/show_bug.cgi?id=2712#desc13.)
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'merge', '-c', '2',
                                     B_url, B_path)
Esempio n. 47
0
def copy_with_mod_from_unreadable_dir_and_copy(sbox):
    "verify copies with mods from unreadable dirs +copy"

    sbox.build("svnsync-copy-with-mod-from-unreadable-dir-and-copy")

    # Make a copy of the B directory.
    svntest.actions.run_and_verify_svn(None, None, [], 'cp',
                                       sbox.wc_dir + '/A/B',
                                       sbox.wc_dir + '/A/P')

    # Copy a (readable) file into the copied directory.
    svntest.actions.run_and_verify_svn(None, None, [], 'cp',
                                       sbox.wc_dir + '/A/D/gamma',
                                       sbox.wc_dir + '/A/P/E')

    # Commit the copy-with-modification.
    svntest.actions.run_and_verify_svn(None, None, [], 'ci', sbox.wc_dir, '-m',
                                       'log_msg')

    # Lock down the source repository.
    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    build_repos(dest_sbox)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    args = tuple(s.authz_name() for s in [sbox, sbox, dest_sbox])
    open(sbox.authz_file, 'w').write("[%s:/]\n"
                                     "* = r\n"
                                     "\n"
                                     "[%s:/A/B]\n"
                                     "* = \n"
                                     "\n"
                                     "[%s:/]\n"
                                     "* = rw" % args)

    run_init(dest_sbox.repo_url, sbox.repo_url)

    run_sync(dest_sbox.repo_url)

    expected_out = [
        'Changed paths:\n',
        '   A /A/P\n',
        '   A /A/P/E\n',
        '   A /A/P/E/alpha\n',
        '   A /A/P/E/beta\n',
        '   A /A/P/E/gamma (from /A/D/gamma:1)\n',
        '   A /A/P/F\n',
        '   A /A/P/lambda\n',
        '\n',
        '\n',  # log message is stripped
    ]

    exit_code, out, err = svntest.main.run_svn(None, 'log', '-r', '2', '-v',
                                               dest_sbox.repo_url)

    if err:
        raise SVNUnexpectedStderr(err)

    svntest.verify.compare_and_display_lines(None, 'LOG', expected_out,
                                             out[2:12])
Esempio n. 48
0
def copy_with_mod_from_unreadable_dir(sbox):
  "verify copies with mods from unreadable dirs"

  sbox.build()

  # Make a copy of the B directory.
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'cp',
                                     sbox.wc_dir + '/A/B',
                                     sbox.wc_dir + '/A/P')

  # Set a property inside the copied directory.
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'pset',
                                     'foo',
                                     'bar',
                                     sbox.wc_dir + '/A/P/lambda')

  # Add a new directory and file inside the copied directory.
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'mkdir',
                                     sbox.wc_dir + '/A/P/NEW-DIR')

  svntest.main.file_append(sbox.wc_dir + '/A/P/E/new-file', "bla bla")
  svntest.main.run_svn(None, 'add', sbox.wc_dir + '/A/P/E/new-file')

  # Delete a file inside the copied directory.
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'rm',
                                     sbox.wc_dir + '/A/P/E/beta')

  # Commit the copy-with-modification.
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'ci',
                                     sbox.wc_dir,
                                     '-m', 'log_msg')

  # Lock down the source repository.
  write_restrictive_svnserve_conf(sbox.repo_dir)

  dest_sbox = sbox.clone_dependent()
  dest_sbox.build(create_wc=False, empty=True)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  src_authz = sbox.authz_name()
  dst_authz = dest_sbox.authz_name()
  write_authz_file(sbox, None,
                   prefixed_rules = {
                       src_authz + ':/':    '* = r',
                       src_authz + ':/A/B': '* =',
                       dst_authz + ':/':    '* = rw',
                       })

  run_init(dest_sbox.repo_url, sbox.repo_url)

  run_sync(dest_sbox.repo_url)

  expected_out = [
    'Changed paths:\n',
    '   A /A/P\n',
    '   A /A/P/E\n',
    '   A /A/P/E/alpha\n',
    '   A /A/P/E/new-file\n',
    '   A /A/P/F\n',
    '   A /A/P/NEW-DIR\n',
    '   A /A/P/lambda\n',
    '\n',
    '\n', # log message is stripped
  ]

  exit_code, out, err = svntest.main.run_svn(None,
                                             'log',
                                             '-r', '2',
                                             '-v',
                                             dest_sbox.repo_url)

  if err:
    raise SVNUnexpectedStderr(err)

  svntest.verify.compare_and_display_lines(None,
                                           'LOG',
                                           expected_out,
                                           out[2:12])

  svntest.actions.run_and_verify_svn(['bar\n'],
                                     [],
                                     'pget',
                                     'foo',
                                     dest_sbox.repo_url + '/A/P/lambda')
Esempio n. 49
0
def diff_unauth_parent(sbox):
  "diff directory without reading parent"

  sbox.build(create_wc=False)

  # Create r2: Change A a bit
  svntest.actions.run_and_verify_svnmucc(None, [],
                                         'propset', 'k', 'v',
                                         sbox.repo_url + '/A',
                                         '-m', 'set prop')

  # Create r3 Mark E and G
  svntest.actions.run_and_verify_svnmucc(None, [],
                                         'propset', 'this-is', 'E',
                                         sbox.repo_url + '/A/B/E',
                                         'propset', 'this-is', 'G',
                                         sbox.repo_url + '/A/D/G',
                                         '-m', 'set prop')

  # Create r4: Replace A/B/E with A/D/G
  svntest.actions.run_and_verify_svnmucc(None, [],
                                         'rm', sbox.repo_url + '/A/B/E',
                                         'cp', '3', sbox.repo_url + '/A/D/G',
                                         sbox.repo_url + '/A/B/E',
                                         '-m', 'replace A/B/E')


  if is_ra_type_svn() or is_ra_type_dav():
    write_restrictive_svnserve_conf(sbox.repo_dir)
    write_authz_file(sbox, {"/"       : "* =",
                            "/A"    : "* = rw"})

  # Diff the property change
  expected_output = [
    'Index: .\n',
    '===================================================================\n',
    '--- .\t(revision 1)\n',
    '+++ .\t(revision 2)\n',
    '\n',
    'Property changes on: .\n',
    '___________________________________________________________________\n',
    'Added: k\n',
    '## -0,0 +1 ##\n',
    '+v\n',
    '\ No newline at end of property\n'
  ]
  svntest.actions.run_and_verify_svn(expected_output, [],
                                     'diff', sbox.repo_url + '/A', '-c', '2')

  if is_ra_type_svn() or is_ra_type_dav():
    write_authz_file(sbox, {"/"       : "* =",
                            "/A/B/E"    : "* = rw"})

  # Diff the replacement
  expected_output = [
    'Index: alpha\n',
    '===================================================================\n',
    '--- alpha\t(revision 3)\n',
    '+++ alpha\t(nonexistent)\n',
    '@@ -1 +0,0 @@\n',
    '-This is the file \'alpha\'.\n',
    'Index: beta\n',
    '===================================================================\n',
    '--- beta\t(revision 3)\n',
    '+++ beta\t(nonexistent)\n',
    '@@ -1 +0,0 @@\n',
    '-This is the file \'beta\'.\n',
    'Index: tau\n',
    '===================================================================\n',
    '--- tau\t(nonexistent)\n',
    '+++ tau\t(revision 4)\n',
    '@@ -0,0 +1 @@\n',
    '+This is the file \'tau\'.\n',
    'Index: rho\n',
    '===================================================================\n',
    '--- rho\t(nonexistent)\n',
    '+++ rho\t(revision 4)\n',
    '@@ -0,0 +1 @@\n',
    '+This is the file \'rho\'.\n',
    'Index: pi\n',
    '===================================================================\n',
    '--- pi\t(nonexistent)\n',
    '+++ pi\t(revision 4)\n',
    '@@ -0,0 +1 @@\n',
    '+This is the file \'pi\'.\n',
  ]

  if is_ra_type_svn() or is_ra_type_dav():
    # Because we can't anchor above C we see just a changed C, not a
    # replacement
    expected_output += [
    'Index: .\n',
    '===================================================================\n',
    '--- .\t(revision 3)\n',
    '+++ .\t(revision 4)\n',
    '\n',
    'Property changes on: .\n',
    '___________________________________________________________________\n',
      'Modified: this-is\n',
      '## -1 +1 ##\n',
      '-E\n',
      '\ No newline at end of property\n',
      '+G\n',
      '\ No newline at end of property\n',
    ]
  else:
    # ### We should also see a property deletion here!
    expected_output += [
    'Index: .\n',
    '===================================================================\n',
    '--- .\t(revision 3)\n',
    '+++ .\t(nonexistent)\n',
    '\n',
    'Property changes on: .\n',
    '___________________________________________________________________\n',
    'Deleted: this-is\n',
    '## -1 +0,0 ##\n',
    '-E\n',
    '\ No newline at end of property\n',
    'Index: .\n',
    '===================================================================\n',
    '--- .\t(nonexistent)\n',
    '+++ .\t(revision 4)\n',
    '\n',
    'Property changes on: .\n',
    '___________________________________________________________________\n',
      'Added: this-is\n',
      '## -0,0 +1 ##\n',
      '+G\n',
      '\ No newline at end of property\n',
    ]

  # Use two url diff, because 'svn diff url -c' uses copyfrom to diff against
  expected_output = svntest.verify.UnorderedOutput(expected_output)
  svntest.actions.run_and_verify_svn(expected_output, [],
                                     'diff', sbox.repo_url + '/A/B/E@3',
                                      sbox.repo_url + '/A/B/E@4',
                                      '--notice-ancestry')

  # Do the same thing with summarize to really see directory deletes and adds
  if is_ra_type_svn() or is_ra_type_dav():
    # With no rights on the parent directory we just see a property change on E
    expected_output = [
      'D       %s/A/B/E/alpha\n' % sbox.repo_url,
      'D       %s/A/B/E/beta\n' % sbox.repo_url,
      'A       %s/A/B/E/tau\n' % sbox.repo_url,
      'A       %s/A/B/E/rho\n' % sbox.repo_url,
      'A       %s/A/B/E/pi\n' % sbox.repo_url,
      ' M      %s/A/B/E\n' % sbox.repo_url,
    ]
  else:
    # But with rights on the parent we see a replacement of E
    expected_output = [
      'D       %s/A/B/E/alpha\n' % sbox.repo_url,
      'D       %s/A/B/E/beta\n' % sbox.repo_url,
      'D       %s/A/B/E\n' % sbox.repo_url,
      'A       %s/A/B/E/tau\n' % sbox.repo_url,
      'A       %s/A/B/E/rho\n' % sbox.repo_url,
      'A       %s/A/B/E/pi\n' % sbox.repo_url,
      'A       %s/A/B/E\n' % sbox.repo_url,
    ]

  expected_output = svntest.verify.UnorderedOutput(expected_output)
  svntest.actions.run_and_verify_svn(expected_output, [],
                                     'diff', sbox.repo_url + '/A/B/E@3',
                                      sbox.repo_url + '/A/B/E@4',
                                      '--notice-ancestry', '--summarize')
def copy_with_mod_from_unreadable_dir_and_copy(sbox):
  "verify copies with mods from unreadable dirs +copy"

  sbox.build("svnsync-copy-with-mod-from-unreadable-dir-and-copy")

  # Make a copy of the B directory.
  svntest.actions.run_and_verify_svn(None,
                                     None,
                                     [],
                                     'cp',
                                     sbox.wc_dir + '/A/B',
                                     sbox.wc_dir + '/A/P')


  # Copy a (readable) file into the copied directory.
  svntest.actions.run_and_verify_svn(None,
                                     None,
                                     [],
                                     'cp',
                                     sbox.wc_dir + '/A/D/gamma',
                                     sbox.wc_dir + '/A/P/E')


  # Commit the copy-with-modification.
  svntest.actions.run_and_verify_svn(None,
                                     None,
                                     [],
                                     'ci',
                                     sbox.wc_dir,
                                     '-m', 'log_msg')

  # Lock down the source repository.
  write_restrictive_svnserve_conf(sbox.repo_dir)

  dest_sbox = sbox.clone_dependent()
  build_repos(dest_sbox)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  fp = open(sbox.authz_file, 'w')

  # For mod_dav_svn's parent path setup we need per-repos permissions in
  # the authz file...
  if sbox.repo_url.startswith('http'):
    fp.write("[svnsync-copy-with-mod-from-unreadable-dir-and-copy:/]\n" +
             "* = r\n" +
             "\n" +
             "[svnsync-copy-with-mod-from-unreadable-dir-and-copy:/A/B]\n" +
             "* = \n" +
             "\n" +
             "[svnsync-copy-with-mod-from-unreadable-dir-and-copy-1:/]\n" +
             "* = rw")

  # Otherwise we can just go with the permissions needed for the source
  # repository.
  else:
    fp.write("[/]\n" +
             "* = r\n" +
             "\n" +
             "[/A/B]\n" +
             "* =\n")
  fp.close()

  run_init(dest_sbox.repo_url, sbox.repo_url)

  run_sync(dest_sbox.repo_url)

  expected_out = [
    'Changed paths:\n',
    '   A /A/P\n',
    '   A /A/P/E\n',
    '   A /A/P/E/alpha\n',
    '   A /A/P/E/beta\n',
    '   A /A/P/E/gamma (from /A/D/gamma:1)\n',
    '   A /A/P/F\n',
    '   A /A/P/lambda\n',
    '\n',
    '\n', # log message is stripped
  ]

  exit_code, out, err = svntest.main.run_svn(None,
                                             'log',
                                             '-r', '2',
                                             '-v',
                                             dest_sbox.repo_url)

  if err:
    raise SVNUnexpectedStderr(err)

  svntest.verify.compare_and_display_lines(None,
                                           'LOG',
                                           expected_out,
                                           out[2:12])
def copy_from_unreadable_dir(sbox):
  "verify that copies from unreadable dirs work"

  sbox.build("svnsync-copy-from-unreadable-dir")

  B_url = sbox.repo_url + '/A/B'
  P_url = sbox.repo_url + '/A/P'

  # Set a property on the directory we're going to copy, and a file in it, to
  # confirm that they're transmitted when we later sync the copied directory
  svntest.actions.run_and_verify_svn(None,
                                     None,
                                     [],
                                     'pset',
                                     'foo',
                                     'bar',
                                     sbox.wc_dir + '/A/B/lambda')

  svntest.actions.run_and_verify_svn(None,
                                     None,
                                     [],
                                     'pset',
                                     'baz',
                                     'zot',
                                     sbox.wc_dir + '/A/B')

  svntest.actions.run_and_verify_svn(None,
                                     None,
                                     [],
                                     'ci',
                                     sbox.wc_dir + '/A/B',
                                     '-m', 'log_msg')

  # Now copy that directory so we'll see it in our synced copy
  svntest.actions.run_and_verify_svn(None,
                                     None,
                                     [],
                                     'cp',
                                     B_url,
                                     P_url,
                                     '-m', 'Copy B to P')

  write_restrictive_svnserve_conf(sbox.repo_dir)

  dest_sbox = sbox.clone_dependent()
  build_repos(dest_sbox)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  fp = open(sbox.authz_file, 'w')

  # For mod_dav_svn's parent path setup we need per-repos permissions in
  # the authz file...
  if sbox.repo_url.startswith('http'):
    fp.write("[svnsync-copy-from-unreadable-dir:/]\n" +
             "* = r\n" +
             "\n" +
             "[svnsync-copy-from-unreadable-dir:/A/B]\n" +
             "* = \n" +
             "\n" +
             "[svnsync-copy-from-unreadable-dir-1:/]\n" +
             "* = rw")

  # Otherwise we can just go with the permissions needed for the source
  # repository.
  else:
    fp.write("[/]\n" +
             "* = r\n" +
             "\n" +
             "[/A/B]\n" +
             "* =\n")
  fp.close()

  run_init(dest_sbox.repo_url, sbox.repo_url)

  run_sync(dest_sbox.repo_url)

  expected_out = [
    'Changed paths:\n',
    '   A /A/P\n',
    '   A /A/P/E\n',
    '   A /A/P/E/alpha\n',
    '   A /A/P/E/beta\n',
    '   A /A/P/F\n',
    '   A /A/P/lambda\n',
    '\n',
    '\n', # log message is stripped
  ]

  exit_code, out, err = svntest.main.run_svn(None,
                                             'log',
                                             '-r', '3',
                                             '-v',
                                             dest_sbox.repo_url)

  if err:
    raise SVNUnexpectedStderr(err)

  svntest.verify.compare_and_display_lines(None,
                                           'LOG',
                                           expected_out,
                                           out[2:11])

  svntest.actions.run_and_verify_svn(None,
                                     ['bar\n'],
                                     [],
                                     'pget',
                                     'foo',
                                     dest_sbox.repo_url + '/A/P/lambda')

  svntest.actions.run_and_verify_svn(None,
                                     ['zot\n'],
                                     [],
                                     'pget',
                                     'baz',
                                     dest_sbox.repo_url + '/A/P')
Esempio n. 52
0
def mergeinfo_and_skipped_paths(sbox):
  "skipped paths get overriding mergeinfo"

  # Test that we override the mergeinfo for child paths which weren't
  # actually merged because they were skipped.
  #
  # This test covers paths skipped because:
  #
  #   1) The source of a merge is inaccessible due to authz restrictions.
  #   2) Destination of merge is inaccessible due to authz restrictions.
  #   3) Source *and* destination of merge is inaccessible due to authz
  #      restrictions.
  #   4) File path is versioned but is missing from disk due to OS deletion.
  #      This isn't technically part of issue #2893 but we handle this case
  #      and it didn't warrant its own test).
  #
  # Eventually we should also test(?):
  #
  #   5) Dir path is versioned but is missing from disk due to an OS deletion.

  sbox.build()
  wc_dir = sbox.wc_dir
  wc_disk, wc_status = set_up_branch(sbox, False, 3)

  # Create a restrictive authz where part of the merge source and part
  # of the target are inaccesible.
  write_restrictive_svnserve_conf(sbox.repo_dir)
  write_authz_file(sbox, {"/"               : svntest.main.wc_author +"=rw",
                          # Make a directory in the merge source inaccessible.
                          "/A/B/E"            : svntest.main.wc_author + "=",
                          # Make a file and dir in the merge destination
                          # inaccessible.
                          "/A_COPY_2/D/H/psi" : svntest.main.wc_author + "=",
                          "/A_COPY_2/D/G" : svntest.main.wc_author + "=",
                          # Make the source and destination inaccessible.
                          "/A_COPY_3/B/E"     : svntest.main.wc_author + "=",
                          })

  # Checkout just the branch under the newly restricted authz.
  wc_restricted = sbox.add_wc_path('restricted')
  svntest.actions.run_and_verify_svn(None, None, [], 'checkout',
                                     sbox.repo_url,
                                     wc_restricted)

  # Some paths we'll use in the second WC.
  A_COPY_path = os.path.join(wc_restricted, "A_COPY")
  A_COPY_2_path = os.path.join(wc_restricted, "A_COPY_2")
  A_COPY_2_H_path = os.path.join(wc_restricted, "A_COPY_2", "D", "H")
  A_COPY_3_path = os.path.join(wc_restricted, "A_COPY_3")
  omega_path = os.path.join(wc_restricted, "A_COPY", "D", "H", "omega")
  zeta_path = os.path.join(wc_dir, "A", "D", "H", "zeta")

  # Restrict access to some more of the merge destination the
  # old fashioned way, delete it via the OS.
  ### TODO: Delete a versioned directory?
  os.remove(omega_path)

  # Merge r4:8 into the restricted WC's A_COPY.
  #
  # We expect A_COPY/B/E to be skipped because we can't access the source
  # and A_COPY/D/H/omega because it is missing.  Since we have A_COPY/B/E
  # we should override it's inherited mergeinfo, giving it just what it
  # inherited from A_COPY before the merge.  omega is missing, but since
  # it is a file we can record the fact that it is missing in its parent
  # directory A_COPY/D/H.
  expected_output = wc.State(A_COPY_path, {
    'D/G/rho'   : Item(status='U '),
    'D/H/psi'   : Item(status='U '),
    })
  expected_status = wc.State(A_COPY_path, {
    ''          : Item(status=' M', wc_rev=8),
    'D/H/chi'   : Item(status='  ', wc_rev=8),
    'D/H/psi'   : Item(status='M ', wc_rev=8),
    'D/H/omega' : Item(status='!M', wc_rev=8),
    'D/H'       : Item(status='  ', wc_rev=8),
    'D/G/pi'    : Item(status='  ', wc_rev=8),
    'D/G/rho'   : Item(status='M ', wc_rev=8),
    'D/G/tau'   : Item(status='  ', wc_rev=8),
    'D/G'       : Item(status='  ', wc_rev=8),
    'D/gamma'   : Item(status='  ', wc_rev=8),
    'D'         : Item(status='  ', wc_rev=8),
    'B/lambda'  : Item(status='  ', wc_rev=8),
    'B/E'       : Item(status=' M', wc_rev=8),
    'B/E/alpha' : Item(status='  ', wc_rev=8),
    'B/E/beta'  : Item(status='  ', wc_rev=8),
    'B/F'       : Item(status='  ', wc_rev=8),
    'B'         : Item(status='  ', wc_rev=8),
    'mu'        : Item(status='  ', wc_rev=8),
    'C'         : Item(status='  ', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:5-8'}),
    'D/H/psi'   : Item("New content"),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
     # 'D/H/omega' : run_and_verify_merge() doesn't support checking
     #               the props on a missing path, so we do that
     #               manually (see below).
    'D/H'       : Item(),
    'D/G/pi'    : Item("This is the file 'pi'.\n"),
    'D/G/rho'   : Item("New content"),
    'D/G/tau'   : Item("This is the file 'tau'.\n"),
    'D/G'       : Item(),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D'         : Item(),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/E'       : Item(props={SVN_PROP_MERGEINFO : ''}),
    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
    'B/E/beta'  : Item("This is the file 'beta'.\n"),
    'B/F'       : Item(),
    'B'         : Item(),
    'mu'        : Item("This is the file 'mu'.\n"),
    'C'         : Item(),
    })
  expected_skip = wc.State(A_COPY_path, {
    'B/E'       : Item(),
    'D/H/omega' : Item(),
    })
  saved_cwd = os.getcwd()
  svntest.actions.run_and_verify_merge(A_COPY_path, '4', '8',
                                       sbox.repo_url + \
                                       '/A',
                                       expected_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1)

  # Manually check the props on A_COPY/D/H/omega.
  svntest.actions.run_and_verify_svn(None, ['\n'], [],
                                    'pg', SVN_PROP_MERGEINFO, omega_path)

  # Merge r4:8 into the restricted WC's A_COPY_2.
  #
  # As before we expect A_COPY_2/B/E to be skipped because we can't access the
  # source but now the destination paths A_COPY_2/D/G, A_COPY_2/D/G/rho, and
  # A_COPY_2/D/H/psi should also be skipped because our test user doesn't have
  # access.
  #
  # After the merge the parents of the missing dest paths, A_COPY_2/D and
  # A_COPY_2/D/H get non-inheritable mergeinfo.  Those parents children that
  # *are* present, A_COPY_2/D/gamma, A_COPY_2/D/H/chi, and A_COPY_2/D/H/omega
  # get their own mergeinfo.  Note that A_COPY_2/D/H is both the parent of
  # a missing child and the sibling of missing child, but the former always
  # takes precedence in terms of getting *non*-inheritable mergeinfo.
  expected_output = wc.State(A_COPY_2_path, {
    'D/G'       : Item(status='  ', treeconflict='C'),
    'D/H/omega' : Item(status='U '),
    })
  expected_status = wc.State(A_COPY_2_path, {
    ''          : Item(status=' M', wc_rev=8),
    'D/G'       : Item(status='! ', treeconflict='C'),
    'D/H/chi'   : Item(status=' M', wc_rev=8),
    'D/H/omega' : Item(status='MM', wc_rev=8),
    'D/H'       : Item(status=' M', wc_rev=8),
    'D/gamma'   : Item(status=' M', wc_rev=8),
    'D'         : Item(status=' M', wc_rev=8),
    'B/lambda'  : Item(status='  ', wc_rev=8),
    'B/E'       : Item(status=' M', wc_rev=8),
    'B/E/alpha' : Item(status='  ', wc_rev=8),
    'B/E/beta'  : Item(status='  ', wc_rev=8),
    'B/F'       : Item(status='  ', wc_rev=8),
    'B'         : Item(status='  ', wc_rev=8),
    'mu'        : Item(status='  ', wc_rev=8),
    'C'         : Item(status='  ', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:5-8'}),
    'D/H/omega' : Item("New content",
                       props={SVN_PROP_MERGEINFO : '/A/D/H/omega:5-8'}),
    'D/H/chi'   : Item("This is the file 'chi'.\n",
                       props={SVN_PROP_MERGEINFO : '/A/D/H/chi:5-8'}),
    'D/H'       : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:5-8*'}),
    'D/gamma'   : Item("This is the file 'gamma'.\n",
                       props={SVN_PROP_MERGEINFO : '/A/D/gamma:5-8'}),
    'D'         : Item(props={SVN_PROP_MERGEINFO : '/A/D:5-8*'}),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/E'       : Item(props={SVN_PROP_MERGEINFO : ''}),
    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
    'B/E/beta'  : Item("This is the file 'beta'.\n"),
    'B/F'       : Item(),
    'B'         : Item(),
    'mu'        : Item("This is the file 'mu'.\n"),
    'C'         : Item(),
    })
  expected_skip = wc.State(A_COPY_2_path, {
    'B/E'     : Item(),
    'D/H/psi'   : Item(),
    })
  saved_cwd = os.getcwd()
  svntest.actions.run_and_verify_merge(A_COPY_2_path, '4', '8',
                                       sbox.repo_url + \
                                       '/A',
                                       expected_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1, 0)

  # Merge r5:7 into the restricted WC's A_COPY_3.
  #
  # Again A_COPY_3/B/E should be skipped, but because we can't access the
  # source *or* the destination we expect its parent A_COPY_3/B to get
  # non-inheritable mergeinfo and its two existing siblings, A_COPY_3/B/F
  # and A_COPY_3/B/lambda to get their own mergeinfo.
  expected_output = wc.State(A_COPY_3_path, {
    'D/G/rho' : Item(status='U '),
    })
  expected_status = wc.State(A_COPY_3_path, {
    ''          : Item(status=' M', wc_rev=8),
    'D/H/chi'   : Item(status='  ', wc_rev=8),
    'D/H/omega' : Item(status='  ', wc_rev=8),
    'D/H/psi'   : Item(status='  ', wc_rev=8),
    'D/H'       : Item(status='  ', wc_rev=8),
    'D/gamma'   : Item(status='  ', wc_rev=8),
    'D'         : Item(status='  ', wc_rev=8),
    'D/G'       : Item(status='  ', wc_rev=8),
    'D/G/pi'    : Item(status='  ', wc_rev=8),
    'D/G/rho'   : Item(status='M ', wc_rev=8),
    'D/G/tau'   : Item(status='  ', wc_rev=8),
    'B/lambda'  : Item(status=' M', wc_rev=8),
    'B/F'       : Item(status=' M', wc_rev=8),
    'B'         : Item(status=' M', wc_rev=8),
    'mu'        : Item(status='  ', wc_rev=8),
    'C'         : Item(status='  ', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:6-7'}),
    'D/H/omega' : Item("This is the file 'omega'.\n"),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
    'D/H/psi'   : Item("This is the file 'psi'.\n"),
    'D/H'       : Item(),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D'         : Item(),
    'D/G'       : Item(),
    'D/G/pi'    : Item("This is the file 'pi'.\n"),
    'D/G/rho'   : Item("New content"),
    'D/G/tau'   : Item("This is the file 'tau'.\n"),
    'B/lambda'  : Item("This is the file 'lambda'.\n",
                       props={SVN_PROP_MERGEINFO : '/A/B/lambda:6-7'}),
    'B/F'       : Item(props={SVN_PROP_MERGEINFO : '/A/B/F:6-7'}),
    'B'         : Item(props={SVN_PROP_MERGEINFO : '/A/B:6-7*'}),
    'mu'        : Item("This is the file 'mu'.\n"),
    'C'         : Item(),
    })
  expected_skip = wc.State(A_COPY_3_path, {'B/E' : Item()})
  saved_cwd = os.getcwd()
  svntest.actions.run_and_verify_merge(A_COPY_3_path, '5', '7',
                                       sbox.repo_url + \
                                       '/A',
                                       expected_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1, 0)
  svntest.actions.run_and_verify_svn(None, None, [], 'revert', '--recursive',
                                     wc_restricted)

  # Test issue #2997.  If a merge requires two separate editor drives and the
  # first is non-operative we should still update the mergeinfo to reflect
  # this.
  #
  # Merge -c5 -c8 to the restricted WC's A_COPY_2/D/H.  r5 gets merged first
  # but is a no-op, r8 get's merged next and is operative so the mergeinfo
  # should be updated to reflect both merges.
  expected_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status='U '),
    })
  expected_status = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' M', wc_rev=8),
    'chi'   : Item(status=' M', wc_rev=8),
    'omega' : Item(status='MM', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:5*,8*'}),
    'omega' : Item("New content",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/omega:5,8'}),
    'chi'   : Item("This is the file 'chi'.\n",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/chi:5,8'}),
    })
  expected_skip = wc.State(A_COPY_2_H_path, {
    'psi'   : Item(),
    })
  saved_cwd = os.getcwd()
  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '4', '5',
                                       sbox.repo_url + \
                                       '/A/D/H',
                                       expected_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1, 0, '-c5', '-c8')

  # Test issue #2829 'Improve handling for skipped paths encountered
  # during a merge'

  # Revert previous changes to restricted WC
  svntest.actions.run_and_verify_svn(None, None, [], 'revert', '--recursive',
                                     wc_restricted)
  # Add new path 'A/D/H/zeta'
  svntest.main.file_write(zeta_path, "This is the file 'zeta'.\n")
  svntest.actions.run_and_verify_svn(None, None, [], 'add', zeta_path)
  expected_output = wc.State(wc_dir, {'A/D/H/zeta' : Item(verb='Adding')})
  wc_status.add({'A/D/H/zeta' : Item(status='  ', wc_rev=9)})
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        wc_status, None, wc_dir)

  # Merge -r7:9 to the restricted WC's A_COPY_2/D/H.
  #
  # r9 adds a path, 'A_COPY_2/D/H/zeta', which has a parent with
  # non-inheritable mergeinfo (due to the fact 'A_COPY_2/D/H/psi' is missing).
  # 'A_COPY_2/D/H/zeta' must therefore get its own explicit mergeinfo from
  # this merge.
  expected_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status='U '),
    'zeta'  : Item(status='A '),
    })
  expected_status = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' M', wc_rev=8),
    'chi'   : Item(status=' M', wc_rev=8),
    'omega' : Item(status='MM', wc_rev=8),
    'zeta'  : Item(status='A ', copied='+', wc_rev='-'),
    })
  expected_disk = wc.State('', {
    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:8-9*'}),
    'omega' : Item("New content",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/omega:8-9'}),
    'chi'   : Item("This is the file 'chi'.\n",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/chi:8-9'}),
    'zeta'  : Item("This is the file 'zeta'.\n",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/zeta:8-9'}),
    })
  expected_skip = wc.State(A_COPY_2_H_path, {})
  saved_cwd = os.getcwd()
  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '7', '9',
                                       sbox.repo_url + \
                                       '/A/D/H',
                                       expected_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, 1, 0)
Esempio n. 53
0
def copy_with_mod_from_unreadable_dir(sbox):
    "verify copies with mods from unreadable dirs"

    sbox.build("svnsync-copy-with-mod-from-unreadable-dir")

    # Make a copy of the B directory.
    svntest.actions.run_and_verify_svn(None, None, [], 'cp',
                                       sbox.wc_dir + '/A/B',
                                       sbox.wc_dir + '/A/P')

    # Set a property inside the copied directory.
    svntest.actions.run_and_verify_svn(None, None, [], 'pset', 'foo', 'bar',
                                       sbox.wc_dir + '/A/P/lambda')

    # Add a new directory and file inside the copied directory.
    svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
                                       sbox.wc_dir + '/A/P/NEW-DIR')

    svntest.main.file_append(sbox.wc_dir + '/A/P/E/new-file', "bla bla")
    svntest.main.run_svn(None, 'add', sbox.wc_dir + '/A/P/E/new-file')

    # Delete a file inside the copied directory.
    svntest.actions.run_and_verify_svn(None, None, [], 'rm',
                                       sbox.wc_dir + '/A/P/E/beta')

    # Commit the copy-with-modification.
    svntest.actions.run_and_verify_svn(None, None, [], 'ci', sbox.wc_dir, '-m',
                                       'log_msg')

    # Lock down the source repository.
    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    build_repos(dest_sbox)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    args = tuple(s.authz_name() for s in [sbox, sbox, dest_sbox])
    open(sbox.authz_file, 'w').write("[%s:/]\n"
                                     "* = r\n"
                                     "\n"
                                     "[%s:/A/B]\n"
                                     "* = \n"
                                     "\n"
                                     "[%s:/]\n"
                                     "* = rw" % args)

    run_init(dest_sbox.repo_url, sbox.repo_url)

    run_sync(dest_sbox.repo_url)

    expected_out = [
        'Changed paths:\n',
        '   A /A/P\n',
        '   A /A/P/E\n',
        '   A /A/P/E/alpha\n',
        '   A /A/P/E/new-file\n',
        '   A /A/P/F\n',
        '   A /A/P/NEW-DIR\n',
        '   A /A/P/lambda\n',
        '\n',
        '\n',  # log message is stripped
    ]

    exit_code, out, err = svntest.main.run_svn(None, 'log', '-r', '2', '-v',
                                               dest_sbox.repo_url)

    if err:
        raise SVNUnexpectedStderr(err)

    svntest.verify.compare_and_display_lines(None, 'LOG', expected_out,
                                             out[2:12])

    svntest.actions.run_and_verify_svn(None, ['bar\n'], [], 'pget', 'foo',
                                       dest_sbox.repo_url + '/A/P/lambda')
Esempio n. 54
0
def copy_with_mod_from_unreadable_dir_and_copy(sbox):
    "verify copies with mods from unreadable dirs +copy"

    sbox.build()

    # Make a copy of the B directory.
    svntest.actions.run_and_verify_svn(None, [], 'cp', sbox.wc_dir + '/A/B',
                                       sbox.wc_dir + '/A/P')

    # Copy a (readable) file into the copied directory.
    svntest.actions.run_and_verify_svn(None, [], 'cp',
                                       sbox.wc_dir + '/A/D/gamma',
                                       sbox.wc_dir + '/A/P/E')

    # Commit the copy-with-modification.
    svntest.actions.run_and_verify_svn(None, [], 'ci', sbox.wc_dir, '-m',
                                       'log_msg')

    # Lock down the source repository.
    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    dest_sbox.build(create_wc=False, empty=True)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    src_authz = sbox.authz_name()
    dst_authz = dest_sbox.authz_name()
    write_authz_file(sbox,
                     None,
                     prefixed_rules={
                         src_authz + ':/': '* = r',
                         src_authz + ':/A/B': '* =',
                         dst_authz + ':/': '* = rw',
                     })

    run_init(dest_sbox.repo_url, sbox.repo_url)

    run_sync(dest_sbox.repo_url)

    expected_out = [
        'Changed paths:\n',
        '   A /A/P\n',
        '   A /A/P/E\n',
        '   A /A/P/E/alpha\n',
        '   A /A/P/E/beta\n',
        '   A /A/P/E/gamma (from /A/D/gamma:1)\n',
        '   A /A/P/F\n',
        '   A /A/P/lambda\n',
        '\n',
        '\n',  # log message is stripped
    ]

    exit_code, out, err = svntest.main.run_svn(None, 'log', '-r', '2', '-v',
                                               dest_sbox.repo_url)

    if err:
        raise SVNUnexpectedStderr(err)

    svntest.verify.compare_and_display_lines(None, 'LOG', expected_out,
                                             out[2:12])
Esempio n. 55
0
def copy_with_mod_from_unreadable_dir_and_copy(sbox):
  "verify copies with mods from unreadable dirs +copy"

  sbox.build()

  # Make a copy of the B directory.
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'cp',
                                     sbox.wc_dir + '/A/B',
                                     sbox.wc_dir + '/A/P')


  # Copy a (readable) file into the copied directory.
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'cp',
                                     sbox.wc_dir + '/A/D/gamma',
                                     sbox.wc_dir + '/A/P/E')


  # Commit the copy-with-modification.
  svntest.actions.run_and_verify_svn(None,
                                     [],
                                     'ci',
                                     sbox.wc_dir,
                                     '-m', 'log_msg')

  # Lock down the source repository.
  write_restrictive_svnserve_conf(sbox.repo_dir)

  dest_sbox = sbox.clone_dependent()
  dest_sbox.build(create_wc=False, empty=True)

  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

  src_authz = sbox.authz_name()
  dst_authz = dest_sbox.authz_name()
  write_authz_file(sbox, None,
                   prefixed_rules = {
                       src_authz + ':/':    '* = r',
                       src_authz + ':/A/B': '* =',
                       dst_authz + ':/':    '* = rw',
                       })

  run_init(dest_sbox.repo_url, sbox.repo_url)

  run_sync(dest_sbox.repo_url)

  expected_out = [
    'Changed paths:\n',
    '   A /A/P\n',
    '   A /A/P/E\n',
    '   A /A/P/E/alpha\n',
    '   A /A/P/E/beta\n',
    '   A /A/P/E/gamma (from /A/D/gamma:1)\n',
    '   A /A/P/F\n',
    '   A /A/P/lambda\n',
    '\n',
    '\n', # log message is stripped
  ]

  exit_code, out, err = svntest.main.run_svn(None,
                                             'log',
                                             '-r', '2',
                                             '-v',
                                             dest_sbox.repo_url)

  if err:
    raise SVNUnexpectedStderr(err)

  svntest.verify.compare_and_display_lines(None,
                                           'LOG',
                                           expected_out,
                                           out[2:12])
Esempio n. 56
0
def mergeinfo_and_skipped_paths(sbox):
  "skipped paths get overriding mergeinfo"

  # Test that we override the mergeinfo for child paths which weren't
  # actually merged because they were skipped.
  #
  # This test covers paths skipped because:
  #
  #   1) The source of a merge is inaccessible due to authz restrictions.
  #   2) Destination of merge is inaccessible due to authz restrictions.
  #   3) Source *and* destination of merge is inaccessible due to authz
  #      restrictions.

  sbox.build()
  wc_dir = sbox.wc_dir
  wc_disk, wc_status = set_up_branch(sbox, False, 3)

  # Create a restrictive authz where part of the merge source and part
  # of the target are inaccesible.
  write_restrictive_svnserve_conf(sbox.repo_dir)
  write_authz_file(sbox, {"/"               : svntest.main.wc_author +"=rw",
                          # Make a directory in the merge source inaccessible.
                          "/A/B/E"            : svntest.main.wc_author + "=",
                          # Make a file and dir in the merge destination
                          # inaccessible.
                          "/A_COPY_2/D/H/psi" : svntest.main.wc_author + "=",
                          "/A_COPY_2/D/G" : svntest.main.wc_author + "=",
                          # Make the source and destination inaccessible.
                          "/A_COPY_3/B/E"     : svntest.main.wc_author + "=",
                          })

  # Checkout just the branch under the newly restricted authz.
  wc_restricted = sbox.add_wc_path('restricted')
  svntest.actions.run_and_verify_svn(None, [], 'checkout',
                                     sbox.repo_url,
                                     wc_restricted)

  # Some paths we'll use in the second WC.
  A_COPY_path = os.path.join(wc_restricted, "A_COPY")
  A_COPY_2_path = os.path.join(wc_restricted, "A_COPY_2")
  A_COPY_2_H_path = os.path.join(wc_restricted, "A_COPY_2", "D", "H")
  A_COPY_3_path = os.path.join(wc_restricted, "A_COPY_3")
  omega_path = os.path.join(wc_restricted, "A_COPY", "D", "H", "omega")
  zeta_path = sbox.ospath("A/D/H/zeta")

  # Merge r4:8 into the restricted WC's A_COPY.
  #
  # We expect A_COPY/B/E to be skipped because we can't access the source
  # and A_COPY/D/H/omega because it is missing.  Since we have A_COPY/B/E
  # we should override it's inherited mergeinfo, giving it just what it
  # inherited from A_COPY before the merge.
  expected_output = wc.State(A_COPY_path, {
    'D/G/rho'   : Item(status='U '),
    'D/H/psi'   : Item(status='U '),
    'D/H/omega' : Item(status='U '),
    })
  expected_mergeinfo_output = wc.State(A_COPY_path, {
    ''          : Item(status=' U'),
    'B/E'       : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_path, {
    })
  expected_status = wc.State(A_COPY_path, {
    ''          : Item(status=' M', wc_rev=8),
    'D/H/chi'   : Item(status='  ', wc_rev=8),
    'D/H/psi'   : Item(status='M ', wc_rev=8),
    'D/H/omega' : Item(status='M ', wc_rev=8),
    'D/H'       : Item(status='  ', wc_rev=8),
    'D/G/pi'    : Item(status='  ', wc_rev=8),
    'D/G/rho'   : Item(status='M ', wc_rev=8),
    'D/G/tau'   : Item(status='  ', wc_rev=8),
    'D/G'       : Item(status='  ', wc_rev=8),
    'D/gamma'   : Item(status='  ', wc_rev=8),
    'D'         : Item(status='  ', wc_rev=8),
    'B/lambda'  : Item(status='  ', wc_rev=8),
    'B/E'       : Item(status=' M', wc_rev=8),
    'B/E/alpha' : Item(status='  ', wc_rev=8),
    'B/E/beta'  : Item(status='  ', wc_rev=8),
    'B/F'       : Item(status='  ', wc_rev=8),
    'B'         : Item(status='  ', wc_rev=8),
    'mu'        : Item(status='  ', wc_rev=8),
    'C'         : Item(status='  ', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:5-8'}),
    'D/H/psi'   : Item("New content"),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
    'D/H/omega' : Item("New content"),
    'D/H'       : Item(),
    'D/G/pi'    : Item("This is the file 'pi'.\n"),
    'D/G/rho'   : Item("New content"),
    'D/G/tau'   : Item("This is the file 'tau'.\n"),
    'D/G'       : Item(),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D'         : Item(),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/E'       : Item(props={SVN_PROP_MERGEINFO : ''}),
    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
    'B/E/beta'  : Item("This is the file 'beta'.\n"),
    'B/F'       : Item(),
    'B'         : Item(),
    'mu'        : Item("This is the file 'mu'.\n"),
    'C'         : Item(),
    })
  expected_skip = wc.State(A_COPY_path, {
    'B/E'       : Item(verb='Skipped missing target'),
    })
  svntest.actions.run_and_verify_merge(A_COPY_path, '4', '8',
                                       sbox.repo_url + '/A', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       check_props=True)

  # Merge r4:8 into the restricted WC's A_COPY_2.
  #
  # As before we expect A_COPY_2/B/E to be skipped because we can't access the
  # source but now the destination paths A_COPY_2/D/G, A_COPY_2/D/G/rho, and
  # A_COPY_2/D/H/psi should also be skipped because our test user doesn't have
  # access.
  #
  # After the merge the parents of the missing dest paths, A_COPY_2/D and
  # A_COPY_2/D/H get non-inheritable mergeinfo.  Those parents' children that
  # *are* present and are affected by the merge, only A_COPY_2/D/H/omega in
  # this case, get their own mergeinfo.  Note that A_COPY_2/D/H is both the
  # parent of a missing child and the sibling of missing child, but the former
  # always takes precedence in terms of getting *non*-inheritable mergeinfo.
  expected_output = wc.State(A_COPY_2_path, {
    'D/H/omega' : Item(status='U '),
    # Below the skip
    'D/G/rho'   : Item(status='  ', treeconflict='U'),
    })
  expected_mergeinfo_output = wc.State(A_COPY_2_path, {
    ''          : Item(status=' U'),
    'D'         : Item(status=' U'),
    'D/H'       : Item(status=' U'),
    'D/H/omega' : Item(status=' U'),
    'B/E'       : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_2_path, {
    })
  expected_status = wc.State(A_COPY_2_path, {
    ''          : Item(status=' M', wc_rev=8),
    'D/H/chi'   : Item(status='  ', wc_rev=8),
    'D/H/omega' : Item(status='MM', wc_rev=8),
    'D/H'       : Item(status=' M', wc_rev=8),
    'D/gamma'   : Item(status='  ', wc_rev=8),
    'D'         : Item(status=' M', wc_rev=8),
    'B/lambda'  : Item(status='  ', wc_rev=8),
    'B/E'       : Item(status=' M', wc_rev=8),
    'B/E/alpha' : Item(status='  ', wc_rev=8),
    'B/E/beta'  : Item(status='  ', wc_rev=8),
    'B/F'       : Item(status='  ', wc_rev=8),
    'B'         : Item(status='  ', wc_rev=8),
    'mu'        : Item(status='  ', wc_rev=8),
    'C'         : Item(status='  ', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:5-8'}),
    'D/H/omega' : Item("New content",
                       props={SVN_PROP_MERGEINFO : '/A/D/H/omega:5-8'}),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
    'D/H'       : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:5-8*'}),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D'         : Item(props={SVN_PROP_MERGEINFO : '/A/D:5-8*'}),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/E'       : Item(props={SVN_PROP_MERGEINFO : ''}),
    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
    'B/E/beta'  : Item("This is the file 'beta'.\n"),
    'B/F'       : Item(),
    'B'         : Item(),
    'mu'        : Item("This is the file 'mu'.\n"),
    'C'         : Item(),
    })
  expected_skip = wc.State(A_COPY_2_path, {
    'B/E'     : Item(verb='Skipped missing target'),
    'D/G'     : Item(verb='Skipped missing target'),
    'D/H/psi' : Item(verb='Skipped missing target'),
    })
  svntest.actions.run_and_verify_merge(A_COPY_2_path, '4', '8',
                                       sbox.repo_url + '/A', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       check_props=True)

  # Merge r5:7 into the restricted WC's A_COPY_3.
  #
  # Again A_COPY_3/B/E should be skipped, but because we can't access the
  # source *or* the destination we expect its parent A_COPY_3/B to get
  # non-inheritable mergeinfo.  A_COPY_3B's two existing siblings,
  # A_COPY_3/B/F and A_COPY_3/B/lambda are untouched by the merge so
  # neither gets any mergeinfo recorded.
  expected_output = wc.State(A_COPY_3_path, {
    'D/G/rho' : Item(status='U '),
    })
  expected_mergeinfo_output = wc.State(A_COPY_3_path, {
    ''  : Item(status=' U'),
    'B' : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_3_path, {
    })
  expected_status = wc.State(A_COPY_3_path, {
    ''          : Item(status=' M', wc_rev=8),
    'D/H/chi'   : Item(status='  ', wc_rev=8),
    'D/H/omega' : Item(status='  ', wc_rev=8),
    'D/H/psi'   : Item(status='  ', wc_rev=8),
    'D/H'       : Item(status='  ', wc_rev=8),
    'D/gamma'   : Item(status='  ', wc_rev=8),
    'D'         : Item(status='  ', wc_rev=8),
    'D/G'       : Item(status='  ', wc_rev=8),
    'D/G/pi'    : Item(status='  ', wc_rev=8),
    'D/G/rho'   : Item(status='M ', wc_rev=8),
    'D/G/tau'   : Item(status='  ', wc_rev=8),
    'B/lambda'  : Item(status='  ', wc_rev=8),
    'B/F'       : Item(status='  ', wc_rev=8),
    'B'         : Item(status=' M', wc_rev=8),
    'mu'        : Item(status='  ', wc_rev=8),
    'C'         : Item(status='  ', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A:6-7'}),
    'D/H/omega' : Item("This is the file 'omega'.\n"),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
    'D/H/psi'   : Item("This is the file 'psi'.\n"),
    'D/H'       : Item(),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D'         : Item(),
    'D/G'       : Item(),
    'D/G/pi'    : Item("This is the file 'pi'.\n"),
    'D/G/rho'   : Item("New content"),
    'D/G/tau'   : Item("This is the file 'tau'.\n"),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/F'       : Item(),
    'B'         : Item(props={SVN_PROP_MERGEINFO : '/A/B:6-7*'}),
    'mu'        : Item("This is the file 'mu'.\n"),
    'C'         : Item(),
    })
  expected_skip = wc.State(A_COPY_3_path,
                           {'B/E' : Item(verb='Skipped missing target')})
  svntest.actions.run_and_verify_merge(A_COPY_3_path, '5', '7',
                                       sbox.repo_url + '/A', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       check_props=True)
  svntest.actions.run_and_verify_svn(None, [], 'revert', '--recursive',
                                     wc_restricted)

  # Test issue #2997.  If a merge requires two separate editor drives and the
  # first is non-operative we should still update the mergeinfo to reflect
  # this.
  #
  # Merge -c5 -c8 to the restricted WC's A_COPY_2/D/H.  r5 gets merged first
  # but is a no-op, r8 get's merged next and is operative so the mergeinfo
  # should be updated on the merge target to reflect both merges.
  expected_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status='U '),
    })
  expected_elision_output = wc.State(A_COPY_2_H_path, {
    })
  expected_status = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' M', wc_rev=8),
    'chi'   : Item(status='  ', wc_rev=8),
    'omega' : Item(status='MM', wc_rev=8),
    })
  expected_disk = wc.State('', {
    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:5*,8*'}),
    'omega' : Item("New content",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/omega:8'}),
    'chi'   : Item("This is the file 'chi'.\n"),
    })
  expected_skip = wc.State(A_COPY_2_H_path, {
    'psi'   : Item(verb='Skipped missing target'),
    })
  # Note we don't bother checking expected mergeinfo output because the
  # multiple merges being performed here, -c5 and -c8, will result in
  # first ' U' and then ' G' mergeinfo notifications.  Our expected
  # tree structures can't handle checking for multiple values for the
  # same key.
  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '4', '5',
                                       sbox.repo_url + '/A/D/H', None,
                                       expected_output,
                                       None, # expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       [], True, False,
                                       '-c5', '-c8',
                                       A_COPY_2_H_path)

  # Test issue #2829 'Improve handling for skipped paths encountered
  # during a merge'

  # Revert previous changes to restricted WC
  svntest.actions.run_and_verify_svn(None, [], 'revert', '--recursive',
                                     wc_restricted)
  # Add new path 'A/D/H/zeta'
  svntest.main.file_write(zeta_path, "This is the file 'zeta'.\n")
  svntest.actions.run_and_verify_svn(None, [], 'add', zeta_path)
  expected_output = wc.State(wc_dir, {'A/D/H/zeta' : Item(verb='Adding')})
  wc_status.add({'A/D/H/zeta' : Item(status='  ', wc_rev=9)})
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        wc_status)

  # Merge -r7:9 to the restricted WC's A_COPY_2/D/H.
  #
  # r9 adds a path, 'A_COPY_2/D/H/zeta', which has a missing sibling 'psi',
  # but since 'psi' is untouched by the merge it isn't skipped, and since it
  # isn't skipped, its parent 'A_COPY_2/D/H' won't get non-inheritable
  # mergeinfo set on it to describe the merge, so none of the parent's
  # children will get explicit mergeinfo -- see issue #4056.
  expected_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status='U '),
    'zeta'  : Item(status='A '),
    })
  expected_mergeinfo_output = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' U'),
    'omega' : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status=' U'),
    })
  expected_status = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' M', wc_rev=8),
    'chi'   : Item(status='  ', wc_rev=8),
    'omega' : Item(status='M ', wc_rev=8),
    'zeta'  : Item(status='A ', copied='+', wc_rev='-'),
    })
  expected_disk = wc.State('', {
    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:8-9'}),
    'omega' : Item("New content"),
    'chi'   : Item("This is the file 'chi'.\n"),
    'zeta'  : Item("This is the file 'zeta'.\n"),
    })
  expected_skip = wc.State(A_COPY_2_H_path, {})
  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '7', '9',
                                       sbox.repo_url + '/A/D/H', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       check_props=True)

  # Merge -r4:9 to the restricted WC's A_COPY_2/D/H.
  #
  # r9 adds a path, 'A_COPY_2/D/H/zeta', which has a parent with
  # non-inheritable mergeinfo (due to the fact 'A_COPY_2/D/H/psi' is missing
  # and skipped). 'A_COPY_2/D/H/zeta' must therefore get its own explicit
  # mergeinfo from this merge.
  svntest.actions.run_and_verify_svn(None, [], 'revert', '--recursive',
                                     wc_restricted)
  expected_output = wc.State(A_COPY_2_H_path, {
    'omega' : Item(status='U '),
    'zeta'  : Item(status='A '),
    })
  expected_mergeinfo_output = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' U'),
    'omega' : Item(status=' U'),
    'zeta'  : Item(status=' U'),
    })
  expected_elision_output = wc.State(A_COPY_2_H_path, {
    })
  expected_status = wc.State(A_COPY_2_H_path, {
    ''      : Item(status=' M', wc_rev=8),
    'chi'   : Item(status='  ', wc_rev=8),
    'omega' : Item(status='MM', wc_rev=8),
    'zeta'  : Item(status='A ', copied='+', wc_rev='-'),
    })
  expected_disk = wc.State('', {
    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:5-9*'}),
    'omega' : Item("New content",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/omega:5-9'}),
    'chi'   : Item("This is the file 'chi'.\n"),
    'zeta'  : Item("This is the file 'zeta'.\n",
                   props={SVN_PROP_MERGEINFO : '/A/D/H/zeta:9'}),
    })
  expected_skip = wc.State(A_COPY_2_H_path, {
    'psi' : Item(verb='Skipped missing target'),
    })
  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '4', '9',
                                       sbox.repo_url + '/A/D/H', None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       check_props=True)
Esempio n. 57
0
def diff_unauth_parent(sbox):
  "diff directory without reading parent"

  sbox.build(create_wc=False)

  # Create r2: Change A a bit
  svntest.actions.run_and_verify_svnmucc(None, [],
                                         'propset', 'k', 'v',
                                         sbox.repo_url + '/A',
                                         '-m', 'set prop')

  # Create r3 Mark E and G
  svntest.actions.run_and_verify_svnmucc(None, [],
                                         'propset', 'this-is', 'E',
                                         sbox.repo_url + '/A/B/E',
                                         'propset', 'this-is', 'G',
                                         sbox.repo_url + '/A/D/G',
                                         '-m', 'set prop')

  # Create r4: Replace A/B/E with A/D/G
  svntest.actions.run_and_verify_svnmucc(None, [],
                                         'rm', sbox.repo_url + '/A/B/E',
                                         'cp', '3', sbox.repo_url + '/A/D/G',
                                         sbox.repo_url + '/A/B/E',
                                         '-m', 'replace A/B/E')


  if is_ra_type_svn() or is_ra_type_dav():
    write_restrictive_svnserve_conf(sbox.repo_dir)
    write_authz_file(sbox, {"/"       : "* =",
                            "/A"    : "* = rw"})

  # Diff the property change
  expected_output = [
    'Index: .\n',
    '===================================================================\n',
    '--- .\t(revision 1)\n',
    '+++ .\t(revision 2)\n',
    '\n',
    'Property changes on: .\n',
    '___________________________________________________________________\n',
    'Added: k\n',
    '## -0,0 +1 ##\n',
    '+v\n',
    '\ No newline at end of property\n'
  ]
  svntest.actions.run_and_verify_svn(expected_output, [],
                                     'diff', sbox.repo_url + '/A', '-c', '2')

  if is_ra_type_svn() or is_ra_type_dav():
    write_authz_file(sbox, {"/"       : "* =",
                            "/A/B/E"    : "* = rw"})

  # Diff the replacement
  expected_output = [
    'Index: alpha\n',
    '===================================================================\n',
    '--- alpha\t(revision 3)\n',
    '+++ alpha\t(nonexistent)\n',
    '@@ -1 +0,0 @@\n',
    '-This is the file \'alpha\'.\n',
    'Index: beta\n',
    '===================================================================\n',
    '--- beta\t(revision 3)\n',
    '+++ beta\t(nonexistent)\n',
    '@@ -1 +0,0 @@\n',
    '-This is the file \'beta\'.\n',
    'Index: tau\n',
    '===================================================================\n',
    '--- tau\t(nonexistent)\n',
    '+++ tau\t(revision 4)\n',
    '@@ -0,0 +1 @@\n',
    '+This is the file \'tau\'.\n',
    'Index: rho\n',
    '===================================================================\n',
    '--- rho\t(nonexistent)\n',
    '+++ rho\t(revision 4)\n',
    '@@ -0,0 +1 @@\n',
    '+This is the file \'rho\'.\n',
    'Index: pi\n',
    '===================================================================\n',
    '--- pi\t(nonexistent)\n',
    '+++ pi\t(revision 4)\n',
    '@@ -0,0 +1 @@\n',
    '+This is the file \'pi\'.\n',
  ]

  if is_ra_type_svn() or is_ra_type_dav():
    # Because we can't anchor above C we see just a changed C, not a
    # replacement
    expected_output += [
    'Index: .\n',
    '===================================================================\n',
    '--- .\t(revision 3)\n',
    '+++ .\t(revision 4)\n',
    '\n',
    'Property changes on: .\n',
    '___________________________________________________________________\n',
      'Modified: this-is\n',
      '## -1 +1 ##\n',
      '-E\n',
      '\ No newline at end of property\n',
      '+G\n',
      '\ No newline at end of property\n',
    ]
  else:
    # ### We should also see a property deletion here!
    expected_output += [
    'Index: .\n',
    '===================================================================\n',
    '--- .\t(revision 3)\n',
    '+++ .\t(nonexistent)\n',
    '\n',
    'Property changes on: .\n',
    '___________________________________________________________________\n',
    'Deleted: this-is\n',
    '## -1 +0,0 ##\n',
    '-E\n',
    '\ No newline at end of property\n',
    'Index: .\n',
    '===================================================================\n',
    '--- .\t(nonexistent)\n',
    '+++ .\t(revision 4)\n',
    '\n',
    'Property changes on: .\n',
    '___________________________________________________________________\n',
      'Added: this-is\n',
      '## -0,0 +1 ##\n',
      '+G\n',
      '\ No newline at end of property\n',
    ]

  # Use two url diff, because 'svn diff url -c' uses copyfrom to diff against
  expected_output = svntest.verify.UnorderedOutput(expected_output)
  svntest.actions.run_and_verify_svn(expected_output, [],
                                     'diff', sbox.repo_url + '/A/B/E@3',
                                      sbox.repo_url + '/A/B/E@4',
                                      '--notice-ancestry')

  # Do the same thing with summarize to really see directory deletes and adds
  if is_ra_type_svn() or is_ra_type_dav():
    # With no rights on the parent directory we just see a property change on E
    expected_output = [
      'D       %s/A/B/E/alpha\n' % sbox.repo_url,
      'D       %s/A/B/E/beta\n' % sbox.repo_url,
      'A       %s/A/B/E/tau\n' % sbox.repo_url,
      'A       %s/A/B/E/rho\n' % sbox.repo_url,
      'A       %s/A/B/E/pi\n' % sbox.repo_url,
      ' M      %s/A/B/E\n' % sbox.repo_url,
    ]
  else:
    # But with rights on the parent we see a replacement of E
    expected_output = [
      'D       %s/A/B/E/alpha\n' % sbox.repo_url,
      'D       %s/A/B/E/beta\n' % sbox.repo_url,
      'D       %s/A/B/E\n' % sbox.repo_url,
      'A       %s/A/B/E/tau\n' % sbox.repo_url,
      'A       %s/A/B/E/rho\n' % sbox.repo_url,
      'A       %s/A/B/E/pi\n' % sbox.repo_url,
      'A       %s/A/B/E\n' % sbox.repo_url,
    ]

  expected_output = svntest.verify.UnorderedOutput(expected_output)
  svntest.actions.run_and_verify_svn(expected_output, [],
                                     'diff', sbox.repo_url + '/A/B/E@3',
                                      sbox.repo_url + '/A/B/E@4',
                                      '--notice-ancestry', '--summarize')
Esempio n. 58
0
def copy_from_unreadable_dir(sbox):
    "verify that copies from unreadable dirs work"

    sbox.build()

    B_url = sbox.repo_url + '/A/B'
    P_url = sbox.repo_url + '/A/P'

    # Set a property on the directory we're going to copy, and a file in it, to
    # confirm that they're transmitted when we later sync the copied directory
    svntest.actions.run_and_verify_svn(None, [], 'pset', 'foo', 'bar',
                                       sbox.wc_dir + '/A/B/lambda')

    svntest.actions.run_and_verify_svn(None, [], 'pset', 'baz', 'zot',
                                       sbox.wc_dir + '/A/B')

    svntest.actions.run_and_verify_svn(None, [], 'ci', sbox.wc_dir + '/A/B',
                                       '-m', 'log_msg')

    # Now copy that directory so we'll see it in our synced copy
    svntest.actions.run_and_verify_svn(None, [], 'cp', B_url, P_url, '-m',
                                       'Copy B to P')

    write_restrictive_svnserve_conf(sbox.repo_dir)

    dest_sbox = sbox.clone_dependent()
    dest_sbox.build(create_wc=False, empty=True)

    svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)

    src_authz = sbox.authz_name()
    dst_authz = dest_sbox.authz_name()
    write_authz_file(sbox,
                     None,
                     prefixed_rules={
                         src_authz + ':/': '* = r',
                         src_authz + ':/A/B': '* =',
                         dst_authz + ':/': '* = rw',
                     })

    run_init(dest_sbox.repo_url, sbox.repo_url)

    run_sync(dest_sbox.repo_url)

    expected_out = [
        'Changed paths:\n',
        '   A /A/P\n',
        '   A /A/P/E\n',
        '   A /A/P/E/alpha\n',
        '   A /A/P/E/beta\n',
        '   A /A/P/F\n',
        '   A /A/P/lambda\n',
        '\n',
        '\n',  # log message is stripped
    ]

    exit_code, out, err = svntest.main.run_svn(None, 'log', '-r', '3', '-v',
                                               dest_sbox.repo_url)

    if err:
        raise SVNUnexpectedStderr(err)

    svntest.verify.compare_and_display_lines(None, 'LOG', expected_out,
                                             out[2:11])

    svntest.actions.run_and_verify_svn(['bar\n'], [], 'pget', 'foo',
                                       dest_sbox.repo_url + '/A/P/lambda')

    svntest.actions.run_and_verify_svn(['zot\n'], [], 'pget', 'baz',
                                       dest_sbox.repo_url + '/A/P')
Esempio n. 59
0
def reintegrate_fails_if_no_root_access(sbox):
  "reintegrate fails if no root access"

  # If a user is authorized to a reintegrate source and target, they
  # should be able to reintegrate, regardless of what authorization
  # they have to parents of the source and target.
  #
  # See http://subversion.tigris.org/issues/show_bug.cgi?id=3242#desc78

  # Some paths we'll care about
  wc_dir = sbox.wc_dir
  A_path          = os.path.join(wc_dir, 'A')
  A_COPY_path     = os.path.join(wc_dir, 'A_COPY')
  beta_COPY_path  = os.path.join(wc_dir, 'A_COPY', 'B', 'E', 'beta')
  rho_COPY_path   = os.path.join(wc_dir, 'A_COPY', 'D', 'G', 'rho')
  omega_COPY_path = os.path.join(wc_dir, 'A_COPY', 'D', 'H', 'omega')
  psi_COPY_path   = os.path.join(wc_dir, 'A_COPY', 'D', 'H', 'psi')
      
  # Copy A@1 to A_COPY in r2, and then make some changes to A in r3-6.
  sbox.build()
  wc_dir = sbox.wc_dir
  expected_disk, expected_status = set_up_branch(sbox)

  # Make a change on the branch, to A_COPY/mu, commit in r7.
  svntest.main.file_write(os.path.join(wc_dir, "A_COPY", "mu"),
                          "Changed on the branch.")
  expected_output = wc.State(wc_dir, {'A_COPY/mu' : Item(verb='Sending')})
  expected_status.tweak('A_COPY/mu', wc_rev=7)
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        expected_status, None, wc_dir)
  expected_disk.tweak('A_COPY/mu', contents='Changed on the branch.')

  # Update the WC.
  svntest.main.run_svn(None, 'up', wc_dir)


  # Sync A_COPY with A.
  expected_output = expected_merge_output([[2,7]],
                                          ['U    ' + beta_COPY_path  + '\n',
                                           'U    ' + rho_COPY_path   + '\n',
                                           'U    ' + omega_COPY_path + '\n',
                                           'U    ' + psi_COPY_path   + '\n',
                                           # Mergeinfo notification
                                           ' U   ' + A_COPY_path     + '\n'])
  svntest.actions.run_and_verify_svn(None, expected_output, [], 'merge',
                                     sbox.repo_url + '/A', A_COPY_path)
  svntest.main.run_svn(None, 'ci', '-m', 'synch A_COPY with A', wc_dir)

  # Update so we are ready for reintegrate.
  svntest.main.run_svn(None, 'up', wc_dir)

  # Change authz file so everybody has access to everything but the root.  
  if is_ra_type_svn() or is_ra_type_dav():
    write_restrictive_svnserve_conf(sbox.repo_dir)
    write_authz_file(sbox, {"/"       : "* =",
                            "/A"      : "* = rw",
                            "/A_COPY" : "* = rw",
                            "/iota"   : "* = rw"})

  # Now reintegrate A_COPY back to A.  The lack of access to the root of the
  # repository shouldn't be a problem.
  expected_output = wc.State(A_path, {
    'mu'           : Item(status='U '),
    })
  expected_disk = wc.State('', {
    ''          : Item(props={SVN_PROP_MERGEINFO : '/A_COPY:2-8'}),
    'B'         : Item(),
    'B/lambda'  : Item("This is the file 'lambda'.\n"),
    'B/E'       : Item(),
    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
    'B/E/beta'  : Item("New content"),
    'B/F'       : Item(),
    'mu'        : Item("Changed on the branch."),
    'C'         : Item(),
    'D'         : Item(),
    'D/gamma'   : Item("This is the file 'gamma'.\n"),
    'D/G'       : Item(),
    'D/G/pi'    : Item("This is the file 'pi'.\n"),
    'D/G/rho'   : Item("New content"),
    'D/G/tau'   : Item("This is the file 'tau'.\n"),
    'D/H'       : Item(),
    'D/H/chi'   : Item("This is the file 'chi'.\n"),
    'D/H/omega' : Item("New content"),
    'D/H/psi'   : Item("New content"),
  })
  expected_status = wc.State(A_path, {
    "B"            : Item(status='  ', wc_rev=8),
    "B/lambda"     : Item(status='  ', wc_rev=8),
    "B/E"          : Item(status='  ', wc_rev=8),
    "B/E/alpha"    : Item(status='  ', wc_rev=8),
    "B/E/beta"     : Item(status='  ', wc_rev=8),
    "B/F"          : Item(status='  ', wc_rev=8),
    "mu"           : Item(status='M ', wc_rev=8),
    "C"            : Item(status='  ', wc_rev=8),
    "D"            : Item(status='  ', wc_rev=8),
    "D/gamma"      : Item(status='  ', wc_rev=8),
    "D/G"          : Item(status='  ', wc_rev=8),
    "D/G/pi"       : Item(status='  ', wc_rev=8),
    "D/G/rho"      : Item(status='  ', wc_rev=8),
    "D/G/tau"      : Item(status='  ', wc_rev=8),
    "D/H"          : Item(status='  ', wc_rev=8),
    "D/H/chi"      : Item(status='  ', wc_rev=8),
    "D/H/omega"    : Item(status='  ', wc_rev=8),
    "D/H/psi"      : Item(status='  ', wc_rev=8),
    ""             : Item(status=' M', wc_rev=8),
  })
  expected_skip = wc.State(A_path, {})
  svntest.actions.run_and_verify_merge(A_path, None, None,
                                       sbox.repo_url + '/A_COPY',
                                       expected_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       None, None, None, None,
                                       None, True, True,
                                       '--reintegrate')