Beispiel #1
0
def svnauthz_validate_txn_test(sbox):
    "test 'svnauthz validate --transaction'"

    sbox.build()
    wc_dir = sbox.wc_dir
    repo_dir = sbox.repo_dir

    logfilepath = os.path.join(repo_dir, 'hooks.log')
    pre_commit_hook = svntest.main.get_pre_commit_hook_path(repo_dir)
    hook_instance = hook_template % (repr(
        svntest.main.svnauthz_binary), repr([('validate', 'A/authz')]))
    svntest.main.create_python_hook_script(pre_commit_hook, hook_instance)

    # Create an authz file
    authz_content = "[/]\n* = rw\n"
    authz_path = os.path.join(wc_dir, 'A/authz')
    svntest.main.file_write(authz_path, authz_content)
    svntest.main.run_svn(None, 'add', authz_path)

    # commit a valid authz file, and check the hook's logfile
    expected_output = wc.State(wc_dir, {'A/authz': Item(verb='Adding')})
    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/authz': Item(status='  ', wc_rev=2),
    })
    if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                             expected_status, None, wc_dir):
        raise svntest.Failure
    expected_data = ['Exit 0\n']
    verify_logfile(logfilepath, expected_data)

    # Add an invalid line to the authz file.
    svntest.main.file_append(authz_path, 'x')
    expected_output = wc.State(wc_dir, {'A/authz': Item(verb='Sending')})
    expected_status.tweak('A/authz', status='  ', wc_rev=3)
    if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                             expected_status, None, wc_dir):
        raise svntest.Failure
    expected_data = svntest.verify.RegexOutput(
        ".*?Error parsing authz file: '.*?'", match_all=False)
    verify_logfile(logfilepath, expected_data, delete_log=False)
    # Check the logfile that our Exit was 1 too
    expected_data = svntest.verify.ExpectedOutput("Exit 1\n", match_all=False)
    verify_logfile(logfilepath, expected_data)

    # Validate a file that doesn't exist and make sure we're exiting with 2.
    hook_instance = hook_template % (repr(
        svntest.main.svnauthz_binary), repr([('validate', 'zilch')]))
    svntest.main.create_python_hook_script(pre_commit_hook, hook_instance)
    svntest.main.file_append(authz_path, 'x')
    expected_status.tweak('A/authz', status='  ', wc_rev=4)
    if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                             expected_status, None, wc_dir):
        raise svntest.Failure
    expected_data = svntest.verify.ExpectedOutput("Exit 2\n", match_all=False)
    verify_logfile(logfilepath, expected_data)
def cat_keyword_expansion(sbox):
  "keyword expanded on cat"

  sbox.build()
  wc_dir = sbox.wc_dir
  mu_path = os.path.join(wc_dir, 'A', 'mu')
  lambda_path = os.path.join(wc_dir, 'A', 'B', 'lambda')

  # Set up A/mu to do $Rev$ keyword expansion
  svntest.main.file_append(mu_path , "$Rev$\n$Author$")
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'propset', 'svn:keywords', 'Rev Author',
                                     mu_path)

  expected_output = wc.State(wc_dir, {
    'A/mu' : Item(verb='Sending'),
    })
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
  expected_status.tweak('A/mu', wc_rev=2)
  svntest.actions.run_and_verify_commit(wc_dir,
                                        expected_output, expected_status,
                                        None, wc_dir)

  # Change the author to value which will get truncated on expansion
  full_author = "x" * 400
  key_author = "x" * 244
  svntest.actions.enable_revprop_changes(sbox.repo_dir)
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'propset', '--revprop', '-r2',
                                     'svn:author', full_author,
                                     sbox.wc_dir)
  svntest.actions.run_and_verify_svn(None, [ full_author ], [],
                                     'propget', '--revprop', '-r2',
                                     'svn:author', '--strict',
                                     sbox.wc_dir)

  # Make another commit so that the last changed revision for A/mu is
  # not HEAD.
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'propset', 'foo', 'bar', lambda_path)
  expected_output = wc.State(wc_dir, {
    'A/B/lambda' : Item(verb='Sending'),
    })
  expected_status.tweak('A/B/lambda', wc_rev=3)
  svntest.actions.run_and_verify_commit(wc_dir,
                                        expected_output, expected_status,
                                        None, wc_dir)

  # At one stage the keywords were expanded to values for the requested
  # revision, not to those committed revision
  svntest.actions.run_and_verify_svn(None,
                                     [ "This is the file 'mu'.\n",
                                       "$Rev: 2 $\n",
                                       "$Author: " + key_author + " $"], [],
                                     'cat', '-r', 'HEAD', mu_path)
Beispiel #3
0
def svnauthz_accessof_repo_test(sbox):
  "test 'svnauthz accessof' on urls"

  sbox.build()
  wc_dir = sbox.wc_dir
  repo_url = sbox.repo_url

  authz_content = "[/]\ngroucho = \ngallagher = rw\n* = r\n" + \
      "[/bios]\n* = rw\n" + \
      "[comedy:/jokes]\ngroucho = rw\n" + \
      "[slapstick:/jokes]\n* =\n"

  # build an authz file and commit it to the repo
  authz_path = os.path.join(wc_dir, 'A', 'authz')
  svntest.main.file_write(authz_path, authz_content)
  svntest.main.run_svn(None, 'add', authz_path)
  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Adding')})
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
  expected_status.add({
    'A/authz'            :  Item(status='  ', wc_rev=2),
  })
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        expected_status)

  # Anonymous access with no path, and no repository should be rw
  # since it returns the highest level of access granted anywhere.
  # So /bios being rw for everyone means this will be rw.
  authz_url = repo_url + "/A/authz"
  svntest.actions.run_and_verify_svnauthz(["rw\n"], None,
                                          0, False, "accessof", authz_url)

  # Anonymous access on /jokes should be r, no repo so won't match
  # the slapstick:/jokes section.
  svntest.actions.run_and_verify_svnauthz(["r\n"], None, 0, False, "accessof",
                                          authz_url, "--path", "/jokes")

  # Anonymous access on /jokes on slapstick repo should be no
  svntest.actions.run_and_verify_svnauthz(["no\n"], None, 0, False, "accessof",
                                          authz_url, "--path", "/jokes",
                                          "--repository", "slapstick")

  # User access with no path, and no repository should be rw
  # since it returns the h ighest level of access anywhere.
  # So /bios being rw for everyone means this will be rw.
  svntest.actions.run_and_verify_svnauthz(["rw\n"], None,
                                          0, False, "accessof", authz_url,
                                          "--username", "groucho")

  # User groucho specified on /jokes with no repo, will not match any of the
  # repo specific sections, so is r since everyone has read access.
  svntest.actions.run_and_verify_svnauthz(["r\n"], None,
                                          0, False, "accessof", authz_url,
                                          "--path", "/jokes", "--username",
                                          "groucho")

  # User groucho specified on /jokes with the repo comedy will be rw
  svntest.actions.run_and_verify_svnauthz(["rw\n"], None, 0, False, "accessof",
                                          authz_url, "--path", "/jokes",
                                          "--username", "groucho",
                                          "--repository", "comedy")
def copy_propset_commit(sbox):
  "copy, propset svn:eol-style, commit"

  sbox.build()
  wc_dir = sbox.wc_dir
  mu_path = os.path.join(wc_dir, 'A', 'mu')
  mu2_path = os.path.join(wc_dir, 'A', 'mu2')

  # Copy and propset
  svntest.actions.run_and_verify_svn(None, None, [], 'copy', mu_path, mu2_path)
  svntest.actions.run_and_verify_svn(None, None, [],
                                     'propset', 'svn:eol-style', 'native',
                                     mu2_path)
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
  expected_status.add({
    'A/mu2' : Item(status='A ', wc_rev='-', copied='+')
    })
  svntest.actions.run_and_verify_status(wc_dir, expected_status)

  # Commit, at one stage this dumped core
  expected_output = wc.State(wc_dir, {
    'A/mu2' : Item(verb='Adding'),
    })
  expected_status.tweak('A/mu2', status='  ', wc_rev=2, copied=None)
  svntest.actions.run_and_verify_commit(wc_dir,
                                        expected_output, expected_status,
                                        None, wc_dir)
Beispiel #5
0
def propset_commit_checkout_nocrash(sbox):
    "propset, commit, check out into another wc"

    sbox.build()
    wc_dir = sbox.wc_dir
    mu_path = os.path.join(wc_dir, 'A', 'mu')

    # Put a keyword in A/mu, commit
    svntest.main.file_append(mu_path, "\n$Rev$")
    expected_output = wc.State(wc_dir, {
        'A/mu': Item(verb='Sending'),
    })
    expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
    expected_status.tweak(wc_rev=1)
    expected_status.tweak('A/mu', wc_rev=2)
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, None, None,
                                          None, None, wc_dir)

    # Set property to do keyword expansion on A/mu, commit.
    svntest.actions.run_and_verify_svn(None, None, [], 'propset',
                                       'svn:keywords', 'Rev', mu_path)
    expected_output = wc.State(wc_dir, {
        'A/mu': Item(verb='Sending'),
    })
    expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
    expected_status.tweak(wc_rev=1)
    expected_status.tweak('A/mu', wc_rev=3)
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, None, None,
                                          None, None, wc_dir)

    # Check out into another wc dir
    other_wc_dir = sbox.add_wc_path('other')
    mu_other_path = os.path.join(other_wc_dir, 'A', 'mu')

    svntest.actions.run_and_verify_svn(None, None, None, 'checkout',
                                       '--username', svntest.main.wc_author,
                                       '--password', svntest.main.wc_passwd,
                                       svntest.main.current_repo_url,
                                       other_wc_dir)

    mu_other_contents = open(mu_other_path).read()
    if mu_other_contents != "This is the file 'mu'.\n$Rev: 3 $":
        print "'%s' does not have the expected contents" % mu_other_path
        raise svntest.Failure
Beispiel #6
0
def non_inheritable_mergeinfo(sbox):
    "non-inheritable mergeinfo shows as merged"

    sbox.build()
    wc_dir = sbox.wc_dir
    expected_disk, expected_status = set_up_branch(sbox)

    # Some paths we'll care about
    A_COPY_path = os.path.join(wc_dir, "A_COPY")
    D_COPY_path = os.path.join(wc_dir, "A_COPY", "D")
    rho_COPY_path = os.path.join(wc_dir, "A_COPY", "D", "G", "rho")

    # Update the WC, then merge r4 from A to A_COPY and r6 from A to A_COPY
    # at --depth empty and commit the merges as r7.
    svntest.actions.run_and_verify_svn(None, ["At revision 6.\n"], [], 'up',
                                       wc_dir)
    expected_status.tweak(wc_rev=6)
    svntest.actions.run_and_verify_svn(
        None, expected_merge_output([[4]], 'U    ' + rho_COPY_path + '\n'), [],
        'merge', '-c4', sbox.repo_url + '/A', A_COPY_path)
    svntest.actions.run_and_verify_svn(
        None,
        [],  # Noop due to shallow depth
        [],
        'merge',
        '-c6',
        sbox.repo_url + '/A',
        A_COPY_path,
        '--depth',
        'empty')
    expected_output = wc.State(wc_dir, {
        'A_COPY': Item(verb='Sending'),
        'A_COPY/D/G/rho': Item(verb='Sending'),
    })
    expected_status.tweak('A_COPY', 'A_COPY/D/G/rho', wc_rev=7)
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, wc_dir)

    # Update the WC a last time to ensure full inheritance.
    svntest.actions.run_and_verify_svn(None, ["At revision 7.\n"], [], 'up',
                                       wc_dir)

    # Despite being non-inheritable, r6 should still show as merged to A_COPY
    # and not eligible for merging.
    svntest.actions.run_and_verify_mergeinfo(
        adjust_error_for_server_version(""), [4, 6], sbox.repo_url + '/A',
        A_COPY_path)
    svntest.actions.run_and_verify_mergeinfo(
        adjust_error_for_server_version(""), [3, 5], sbox.repo_url + '/A',
        A_COPY_path, '--show-revs', 'eligible')
    # But if we drop down to A_COPY/D, r6 should show as eligible because it
    # was only merged into A_COPY, no deeper.
    svntest.actions.run_and_verify_mergeinfo(
        adjust_error_for_server_version(""), [4], sbox.repo_url + '/A/D',
        D_COPY_path)
    svntest.actions.run_and_verify_mergeinfo(
        adjust_error_for_server_version(""), [3, 6], sbox.repo_url + '/A/D',
        D_COPY_path, '--show-revs', 'eligible')
Beispiel #7
0
def import_and_checkout(sbox):
  """import and checkout"""

  sbox.build(read_only = True)

  other_repo_dir, other_repo_url = sbox.add_repo_path("other")
  import_from_dir = sbox.add_wc_path("other")

  # Export greek tree to import_from_dir
  expected_output = svntest.main.greek_state.copy()
  expected_output.wc_dir = import_from_dir
  expected_output.desc[''] = Item()
  expected_output.tweak(contents=None, status='A ')
  svntest.actions.run_and_verify_export(sbox.repo_url,
                                        import_from_dir,
                                        expected_output,
                                        svntest.main.greek_state.copy())

  # Create the 'other' repos
  svntest.main.create_repos(other_repo_dir)

  # Import import_from_dir to the other repos
  expected_output = svntest.wc.State(sbox.wc_dir, {})

  svntest.actions.run_and_verify_svn(None, None, [], 'import',
                                     '-m', 'import', import_from_dir,
                                     other_repo_url)

  expected_output = wc.State(import_from_dir, {
    "A"           : Item(status='E '),
    "A/B"         : Item(status='E '),
    "A/B/lambda"  : Item(status='E '),
    "A/B/E"       : Item(status='E '),
    "A/B/E/alpha" : Item(status='E '),
    "A/B/E/beta"  : Item(status='E '),
    "A/B/F"       : Item(status='E '),
    "A/mu"        : Item(status='E '),
    "A/C"         : Item(status='E '),
    "A/D"         : Item(status='E '),
    "A/D/gamma"   : Item(status='E '),
    "A/D/G"       : Item(status='E '),
    "A/D/G/pi"    : Item(status='E '),
    "A/D/G/rho"   : Item(status='E '),
    "A/D/G/tau"   : Item(status='E '),
    "A/D/H"       : Item(status='E '),
    "A/D/H/chi"   : Item(status='E '),
    "A/D/H/omega" : Item(status='E '),
    "A/D/H/psi"   : Item(status='E '),
    "iota"        : Item(status='E ')
    })

  expected_wc = svntest.main.greek_state.copy()

  svntest.actions.run_and_verify_checkout(other_repo_url, import_from_dir,
                                          expected_output, expected_wc,
                                          None, None, None, None,
                                          '--force')
Beispiel #8
0
def svnauthz_compat_mode_repo_test(sbox):
  "test 'svnauthz-validate' compatibility mode url"

  sbox.build()
  wc_dir = sbox.wc_dir
  repo_url = sbox.repo_url

  # Create an authz file
  authz_content = "[/]\n* = rw\n"
  authz_path = os.path.join(wc_dir, 'A/authz')
  svntest.main.file_write(authz_path, authz_content)
  authz_url = repo_url + '/A/authz'

  # Commit the file and check a URL
  svntest.main.run_svn(None, 'add', authz_path)
  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Adding')})
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
  expected_status.add({
    'A/authz'            :  Item(status='  ', wc_rev=2),
  })
  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                           expected_status, None, wc_dir):
    raise svntest.Failure
  svntest.actions.run_and_verify_svnauthz("svnauthz-validate on url",
                                          None, None, 0, True,
                                          authz_url)

  # Check an invalid url.
  svntest.main.file_append(authz_path, "x\n")
  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Sending')})
  expected_status.tweak('A/authz', status='  ', wc_rev=3)
  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                           expected_status, None, wc_dir):
    raise svntest.Failure
  svntest.actions.run_and_verify_svnauthz("svnauthz-validate on invalid file",
                                          None, None, 1, True,
                                          authz_path)

  # Check a non-existant url.
  # Exit code really should be 2 since this is an operational error.
  svntest.actions.run_and_verify_svnauthz(
      "svnauthz-validate on non-existant file", None, None, 2, True,
      repo_url + "/zilch"
  )
Beispiel #9
0
def cat_keyword_expansion(sbox):
    "keyword expanded on cat"

    sbox.build()
    wc_dir = sbox.wc_dir
    mu_path = os.path.join(wc_dir, 'A', 'mu')
    lambda_path = os.path.join(wc_dir, 'A', 'B', 'lambda')

    # Set up A/mu to do $Rev$ keyword expansion
    svntest.main.file_append(mu_path, "\n$Rev$")
    svntest.actions.run_and_verify_svn(None, None, [], 'propset',
                                       'svn:keywords', 'Rev', mu_path)

    expected_output = wc.State(wc_dir, {
        'A/mu': Item(verb='Sending'),
    })
    expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
    expected_status.tweak(wc_rev=1)
    expected_status.tweak('A/mu', wc_rev=2)
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, None, None,
                                          None, None, wc_dir)

    # Make another commit so that the last changed revision for A/mu is
    # not HEAD.
    svntest.actions.run_and_verify_svn(None, None, [], 'propset', 'foo', 'bar',
                                       lambda_path)
    expected_output = wc.State(wc_dir, {
        'A/B/lambda': Item(verb='Sending'),
    })
    expected_status.tweak('A/B/lambda', wc_rev=3)
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, None, None,
                                          None, None, wc_dir)

    # At one stage the keywords were expanded to values for the requested
    # revision, not to those committed revision
    svntest.actions.run_and_verify_svn(
        None, ["This is the file 'mu'.\n", "$Rev: 2 $"], None, 'cat', '-r',
        'HEAD', mu_path)
Beispiel #10
0
def noninheritable_mergeinfo_test_set_up(sbox):
    '''Starting with standard greek tree, copy 'A' to 'branch' in r2 and
  then made a file edit to A/B/lambda in r3.
  Return (expected_output, expected_mergeinfo_output, expected_elision_output,
          expected_status, expected_disk, expected_skip) for a merge of
  r3 from ^/A/B to branch/B.'''

    sbox.build()
    wc_dir = sbox.wc_dir

    lambda_path = sbox.ospath('A/B/lambda')
    B_branch_path = sbox.ospath('branch/B')

    # r2 - Branch ^/A to ^/branch.
    main.run_svn(None, 'copy', sbox.repo_url + '/A', sbox.repo_url + '/branch',
                 '-m', 'make a branch')

    # r3 - Make an edit to A/B/lambda.
    main.file_write(lambda_path, "trunk edit.\n")
    main.run_svn(None, 'commit', '-m', 'file edit', wc_dir)
    main.run_svn(None, 'up', wc_dir)

    expected_output = wc.State(B_branch_path, {
        'lambda': Item(status='U '),
    })
    expected_mergeinfo_output = wc.State(B_branch_path, {
        '': Item(status=' U'),
        'lambda': Item(status=' U'),
    })
    expected_elision_output = wc.State(B_branch_path, {
        'lambda': Item(status=' U'),
    })
    expected_status = wc.State(
        B_branch_path, {
            '': Item(status=' M'),
            'lambda': Item(status='M '),
            'E': Item(status='  '),
            'E/alpha': Item(status='  '),
            'E/beta': Item(status='  '),
            'F': Item(status='  '),
        })
    expected_status.tweak(wc_rev='3')
    expected_disk = wc.State(
        '', {
            '': Item(props={SVN_PROP_MERGEINFO: '/A/B:3'}),
            'lambda': Item("trunk edit.\n"),
            'E': Item(),
            'E/alpha': Item("This is the file 'alpha'.\n"),
            'E/beta': Item("This is the file 'beta'.\n"),
            'F': Item(),
        })
    expected_skip = wc.State(B_branch_path, {})

    return expected_output, expected_mergeinfo_output, expected_elision_output, \
      expected_status, expected_disk, expected_skip
Beispiel #11
0
    def copy_A(dest_name, rev):
        expected = verify.UnorderedOutput([
            "A         " + sbox.ospath(path_join(dest_name, p)) + "\n"
            for p in A_paths
        ])
        expected_status.add({
            path_join(dest_name, p): Item(status='  ', wc_rev=rev)
            for p in A_paths
        })
        expected_disk.add(
            {path_join(dest_name, p): greek_file_item(p)
             for p in A_paths})

        # Make a branch A_COPY to merge into.
        actions.run_and_verify_svn(expected, [], 'copy', sbox.repo_url + "/A",
                                   os.path.join(wc_dir, dest_name))

        expected_output = wc.State(wc_dir, {dest_name: Item(verb='Adding')})
        actions.run_and_verify_commit(wc_dir, expected_output, expected_status)
Beispiel #12
0
def svnauthz_validate_repo_test(sbox):
    "test 'svnauthz validate' on urls"

    sbox.build()
    wc_dir = sbox.wc_dir
    repo_url = sbox.repo_url

    authz_content = "[/]\n* = rw\n"

    # build an authz file and commit it to the repo
    authz_path = os.path.join(wc_dir, 'A', 'authz')
    svntest.main.file_write(authz_path, authz_content)
    svntest.main.run_svn(None, 'add', authz_path)
    expected_output = wc.State(wc_dir, {'A/authz': Item(verb='Adding')})
    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/authz': Item(status='  ', wc_rev=2),
    })
    if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                             expected_status, None, wc_dir):
        raise svntest.Failure

    # Valid authz url (file stored in repo)
    authz_url = repo_url + '/A/authz'
    svntest.actions.run_and_verify_svnauthz("Valid authz url", None, None, 0,
                                            False, "validate", authz_url)

    # Invalid authz url (again use the iota file in the repo)
    # expect exit code 1, we found the file loaded it but found an error
    iota_url = repo_url + '/iota'
    svntest.actions.run_and_verify_svnauthz("Invalid authz url", None, None, 1,
                                            False, "validate", iota_url)

    # Non-existant authz url
    # exit code 2, operational error since we can't test the file.
    svntest.actions.run_and_verify_svnauthz("Non-existant authz file", None,
                                            None, 2, False, "validate",
                                            repo_url + "/zilch")
def checkout_wc_from_drive(sbox):
    "checkout from the root of a Windows drive"

    def find_the_next_available_drive_letter():
        "find the first available drive"

        # get the list of used drive letters, use some Windows specific function.
        try:
            import win32api

            drives = win32api.GetLogicalDriveStrings()
            drives = drives.split('\000')

            for d in range(ord('G'), ord('Z') + 1):
                drive = chr(d)
                if not drive + ':\\' in drives:
                    return drive
        except ImportError:
            # In ActiveState python x64 win32api is not available
            for d in range(ord('G'), ord('Z') + 1):
                drive = chr(d)
                if not os.path.isdir(drive + ':\\'):
                    return drive

        return None

    # Skip the test if not on Windows
    if not svntest.main.windows:
        raise svntest.Skip

    # just create an empty folder, we'll checkout later.
    sbox.build(create_wc=False)
    svntest.main.safe_rmtree(sbox.wc_dir)
    os.mkdir(sbox.wc_dir)

    # create a virtual drive to the working copy folder
    drive = find_the_next_available_drive_letter()
    if drive is None:
        raise svntest.Skip

    subprocess.call(['subst', drive + ':', sbox.repo_dir])
    repo_url = 'file:///' + drive + ':/'
    wc_dir = sbox.wc_dir
    was_cwd = os.getcwd()

    try:
        expected_wc = svntest.main.greek_state.copy()
        expected_output = wc.State(
            wc_dir, {
                'A': Item(status='A '),
                'A/D': Item(status='A '),
                'A/D/H': Item(status='A '),
                'A/D/H/psi': Item(status='A '),
                'A/D/H/chi': Item(status='A '),
                'A/D/H/omega': Item(status='A '),
                'A/D/G': Item(status='A '),
                'A/D/G/tau': Item(status='A '),
                'A/D/G/pi': Item(status='A '),
                'A/D/G/rho': Item(status='A '),
                'A/D/gamma': Item(status='A '),
                'A/C': Item(status='A '),
                'A/mu': Item(status='A '),
                'A/B': 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 '),
                'A/B/lambda': Item(status='A '),
                'iota': Item(status='A '),
            })
        svntest.actions.run_and_verify_checkout(repo_url, wc_dir,
                                                expected_output, expected_wc,
                                                None, None, None, None,
                                                '--force')

    finally:
        os.chdir(was_cwd)
        # cleanup the virtual drive
        subprocess.call(['subst', '/D', drive + ':'])
Beispiel #14
0
def merge_fails_if_subtree_is_deleted_on_src(sbox):
  "merge fails if subtree is deleted on src"

  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2876. ##

  # Create a WC
  sbox.build()
  wc_dir = sbox.wc_dir

  if is_ra_type_svn() or is_ra_type_dav():
    write_authz_file(sbox, {"/" : "* = rw",
                            "/unrelated" : ("* =\n" +
                             svntest.main.wc_author2 + " = rw")})

  # Some paths we'll care about
  Acopy_path = os.path.join(wc_dir, 'A_copy')
  gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
  Acopy_gamma_path = os.path.join(wc_dir, 'A_copy', 'D', 'gamma')
  Acopy_D_path = os.path.join(wc_dir, 'A_copy', 'D')
  A_url = sbox.repo_url + '/A'
  Acopy_url = sbox.repo_url + '/A_copy'

  # Contents to be added to 'gamma'
  new_content = "line1\nline2\nline3\nline4\nline5\n"

  svntest.main.file_write(gamma_path, new_content)

  # Create expected output tree for commit
  expected_output = wc.State(wc_dir, {
    'A/D/gamma' : Item(verb='Sending'),
    })

  # Create expected status tree for commit
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
  expected_status.tweak('A/D/gamma', wc_rev=2)

  # Commit the new content
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        expected_status, None, wc_dir)

  svntest.actions.run_and_verify_svn(None, None, [], 'cp', A_url, Acopy_url,
                                     '-m', 'create a new copy of A')

  # Update working copy
  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)

  svntest.main.file_substitute(gamma_path, "line1", "this is line1")
  # Create expected output tree for commit
  expected_output = wc.State(wc_dir, {
    'A/D/gamma' : Item(verb='Sending'),
    })

  # Create expected status tree for commit
  expected_status.tweak(wc_rev=3)
  expected_status.tweak('A/D/gamma', wc_rev=4)
  expected_status.add({
    'A_copy'          : Item(status='  ', wc_rev=3),
    'A_copy/B'        : Item(status='  ', wc_rev=3),
    'A_copy/B/lambda' : Item(status='  ', wc_rev=3),
    'A_copy/B/E'      : Item(status='  ', wc_rev=3),
    'A_copy/B/E/alpha': Item(status='  ', wc_rev=3),
    'A_copy/B/E/beta' : Item(status='  ', wc_rev=3),
    'A_copy/B/F'      : Item(status='  ', wc_rev=3),
    'A_copy/mu'       : Item(status='  ', wc_rev=3),
    'A_copy/C'        : Item(status='  ', wc_rev=3),
    'A_copy/D'        : Item(status='  ', wc_rev=3),
    'A_copy/D/gamma'  : Item(status='  ', wc_rev=3),
    'A_copy/D/G'      : Item(status='  ', wc_rev=3),
    'A_copy/D/G/pi'   : Item(status='  ', wc_rev=3),
    'A_copy/D/G/rho'  : Item(status='  ', wc_rev=3),
    'A_copy/D/G/tau'  : Item(status='  ', wc_rev=3),
    'A_copy/D/H'      : Item(status='  ', wc_rev=3),
    'A_copy/D/H/chi'  : Item(status='  ', wc_rev=3),
    'A_copy/D/H/omega': Item(status='  ', wc_rev=3),
    'A_copy/D/H/psi'  : Item(status='  ', wc_rev=3),
    })

  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        expected_status, None, wc_dir)

  # Delete A/D/gamma from working copy
  svntest.actions.run_and_verify_svn(None, None, [], 'delete', gamma_path)
  # Create expected output tree for commit
  expected_output = wc.State(wc_dir, {
    'A/D/gamma' : Item(verb='Deleting'),
    })

  expected_status.remove('A/D/gamma')

  svntest.actions.run_and_verify_commit(wc_dir,
                                        expected_output,
                                        expected_status,
                                        None,
                                        wc_dir, wc_dir)
  svntest.actions.run_and_verify_svn(None, expected_merge_output([[3,4]],
                                     'U    ' + Acopy_gamma_path + '\n'),
                                     [], 'merge', '-r1:4',
                                     A_url + '/D/gamma' + '@4',
                                     Acopy_gamma_path)

  # r6: create an empty (unreadable) commit.
  # Empty or unreadable revisions used to crash a svn 1.6+ client when
  # used with a 1.5 server:
  # http://svn.haxx.se/dev/archive-2009-04/0476.shtml
  svntest.main.run_svn(None, 'mkdir', sbox.repo_url + '/unrelated',
                       '--username', svntest.main.wc_author2,
                       '-m', 'creating a rev with no paths.')

  # This merge causes a tree conflict. Since the result of the previous
  # merge of A/D/gamma into A_copy/D has not yet been committed, it is
  # considered a local modification of A_Copy/D/gamma by the following
  # merge. A delete merged ontop of a modified file is a tree conflict.
  # See notes/tree-conflicts/detection.txt
  svntest.actions.run_and_verify_svn(None, expected_merge_output([[6], [3,6]],
                                     ['D    ' + Acopy_gamma_path + '\n',
                                     'C    ' + Acopy_D_path + '\n']),
                                     [], 'merge', '-r1:6', '--force',
                                     A_url, Acopy_path)
Beispiel #15
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)
Beispiel #16
0
def no_mergeinfo_on_tree_conflict_victim(sbox):
    "do not record mergeinfo on tree conflict victims"
    sbox.build()

    # Create a branch of A called A_copy
    sbox.simple_copy('A', 'A_copy')
    sbox.simple_commit()

    # Add a new directory and file on both branches
    sbox.simple_mkdir('A/dir')
    sbox.simple_add_text('new file', 'A/dir/f')
    sbox.simple_commit()

    sbox.simple_mkdir('A_copy/dir')
    sbox.simple_add_text('new file', 'A_copy/dir/f')
    sbox.simple_commit()

    # Run a merge from A to A_copy
    expected_output = wc.State(
        sbox.ospath('A_copy'), {
            'dir': Item(status='  ', treeconflict='C'),
            'dir/f': Item(status='  ', treeconflict='A'),
        })
    expected_mergeinfo_output = wc.State(sbox.ospath('A_copy'), {
        '': Item(status=' U'),
    })
    expected_elision_output = wc.State(sbox.ospath('A_copy'), {})

    expected_disk = svntest.wc.State(
        '', {
            'C': Item(),
            'B/E/beta': Item(contents="This is the file 'beta'.\n"),
            'B/E/alpha': Item(contents="This is the file 'alpha'.\n"),
            'B/lambda': Item(contents="This is the file 'lambda'.\n"),
            'B/F': Item(),
            'D/H/omega': Item(contents="This is the file 'omega'.\n"),
            'D/H/psi': Item(contents="This is the file 'psi'.\n"),
            'D/H/chi': Item(contents="This is the file 'chi'.\n"),
            'D/G/tau': Item(contents="This is the file 'tau'.\n"),
            'D/G/pi': Item(contents="This is the file 'pi'.\n"),
            'D/G/rho': Item(contents="This is the file 'rho'.\n"),
            'D/gamma': Item(contents="This is the file 'gamma'.\n"),
            'dir/f': Item(contents="new file"),
            'mu': Item(contents="This is the file 'mu'.\n"),
        })

    # The merge will create an add vs add tree conflict on A_copy/dir
    expected_status = svntest.wc.State(
        sbox.ospath('A_copy'), {
            '': Item(status=' M', wc_rev='4'),
            'D': Item(status='  ', wc_rev='4'),
            'D/G': Item(status='  ', wc_rev='4'),
            'D/G/pi': Item(status='  ', wc_rev='4'),
            'D/G/rho': Item(status='  ', wc_rev='4'),
            'D/G/tau': Item(status='  ', wc_rev='4'),
            'D/H': Item(status='  ', wc_rev='4'),
            'D/H/psi': Item(status='  ', wc_rev='4'),
            'D/H/omega': Item(status='  ', wc_rev='4'),
            'D/H/chi': Item(status='  ', wc_rev='4'),
            'D/gamma': Item(status='  ', wc_rev='4'),
            'B': Item(status='  ', wc_rev='4'),
            'B/F': Item(status='  ', wc_rev='4'),
            'B/E': Item(status='  ', wc_rev='4'),
            'B/E/alpha': Item(status='  ', wc_rev='4'),
            'B/E/beta': Item(status='  ', wc_rev='4'),
            'B/lambda': Item(status='  ', wc_rev='4'),
            'C': Item(status='  ', wc_rev='4'),
            'dir': Item(status='  ', treeconflict='C', wc_rev='4'),
            'dir/f': Item(status='  ', wc_rev='4'),
            'mu': Item(status='  ', wc_rev='4'),
        })

    expected_skip = wc.State('', {})

    sbox.simple_update('A_copy')
    svntest.actions.run_and_verify_merge(
        sbox.ospath('A_copy'),
        None,
        None,  # rev1, rev2
        '^/A',
        None,  # URL2
        expected_output,
        expected_mergeinfo_output,
        expected_elision_output,
        expected_disk,
        expected_status,
        expected_skip)

    # Resolve the tree conflict by accepting the working copy state left
    # behind by the merge. This preserves the line of history of A_copy/dir,
    # which originated on the branch 'A_copy', rather than replacing it with
    # Jthe line f history of A/dir which originated on branch 'A'
    svntest.actions.run_and_verify_resolve([sbox.ospath('A_copy/dir')],
                                           '--accept', 'working',
                                           sbox.ospath('A_copy/dir'))
    sbox.simple_commit('A_copy')

    # Now try to merge the 'A_copy' branch back to 'A"
    expected_output = wc.State(
        sbox.ospath('A'),
        {
            'dir': Item(status='R '),  # changes line of history of A/dir
            'dir/f': Item(status='A '),
        })
    expected_mergeinfo_output = wc.State(sbox.ospath('A'), {
        '': Item(status=' U'),
    })
    expected_elision_output = wc.State(sbox.ospath('A'), {})

    expected_disk = svntest.wc.State(
        '', {
            'C': Item(),
            'B/E/beta': Item(contents="This is the file 'beta'.\n"),
            'B/E/alpha': Item(contents="This is the file 'alpha'.\n"),
            'B/F': Item(),
            'B/lambda': Item(contents="This is the file 'lambda'.\n"),
            'D/H/omega': Item(contents="This is the file 'omega'.\n"),
            'D/H/psi': Item(contents="This is the file 'psi'.\n"),
            'D/H/chi': Item(contents="This is the file 'chi'.\n"),
            'D/G/tau': Item(contents="This is the file 'tau'.\n"),
            'D/G/pi': Item(contents="This is the file 'pi'.\n"),
            'D/G/rho': Item(contents="This is the file 'rho'.\n"),
            'D/gamma': Item(contents="This is the file 'gamma'.\n"),
            'dir/f': Item(contents="new file"),
            'mu': Item(contents="This is the file 'mu'.\n"),
        })

    expected_status = svntest.wc.State(
        sbox.ospath('A'), {
            '': Item(status=' M', wc_rev='5'),
            'dir': Item(status='R ', copied='+', wc_rev='-'),
            'dir/f': Item(status='  ', copied='+', wc_rev='-'),
            'D': Item(status='  ', wc_rev='5'),
            'D/H': Item(status='  ', wc_rev='5'),
            'D/H/chi': Item(status='  ', wc_rev='5'),
            'D/H/omega': Item(status='  ', wc_rev='5'),
            'D/H/psi': Item(status='  ', wc_rev='5'),
            'D/G': Item(status='  ', wc_rev='5'),
            'D/G/pi': Item(status='  ', wc_rev='5'),
            'D/G/rho': Item(status='  ', wc_rev='5'),
            'D/G/tau': Item(status='  ', wc_rev='5'),
            'D/gamma': Item(status='  ', wc_rev='5'),
            'B': Item(status='  ', wc_rev='5'),
            'B/E': Item(status='  ', wc_rev='5'),
            'B/E/beta': Item(status='  ', wc_rev='5'),
            'B/E/alpha': Item(status='  ', wc_rev='5'),
            'B/lambda': Item(status='  ', wc_rev='5'),
            'B/F': Item(status='  ', wc_rev='5'),
            'mu': Item(status='  ', wc_rev='5'),
            'C': Item(status='  ', wc_rev='5'),
        })

    expected_skip = wc.State('', {})
    sbox.simple_update('A')
    svntest.actions.run_and_verify_merge(
        sbox.ospath('A'),
        None,
        None,  # rev1, rev2
        '^/A_copy',
        None,  # URL2
        expected_output,
        expected_mergeinfo_output,
        expected_elision_output,
        expected_disk,
        expected_status,
        expected_skip)
    sbox.simple_commit('A')
Beispiel #17
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')
Beispiel #18
0
def revert_file_merge_replace_with_history(sbox):
    "revert a merge replacement of file with history"

    sbox.build()
    wc_dir = sbox.wc_dir

    # File scheduled for deletion
    rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
    svntest.actions.run_and_verify_svn(None, None, [], 'rm', rho_path)

    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.tweak('A/D/G/rho', status='D ')
    svntest.actions.run_and_verify_status(wc_dir, expected_status)

    expected_output = svntest.wc.State(wc_dir, {
        'A/D/G/rho': Item(verb='Deleting'),
    })

    expected_status.remove('A/D/G/rho')

    # Commit rev 2
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, wc_dir)
    # create new rho file
    svntest.main.file_write(rho_path, "new rho\n")

    # Add the new file
    svntest.actions.run_and_verify_svn(None, None, [], 'add', rho_path)

    # Commit revsion 3
    expected_status.add({'A/D/G/rho': Item(status='A ', wc_rev='0')})
    svntest.actions.run_and_verify_status(wc_dir, expected_status)
    expected_output = svntest.wc.State(wc_dir, {
        'A/D/G/rho': Item(verb='Adding'),
    })

    svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
                                          wc_dir)

    # Update working copy
    expected_output = svntest.wc.State(wc_dir, {})
    expected_disk = svntest.main.greek_state.copy()
    expected_disk.tweak('A/D/G/rho', contents='new rho\n')
    expected_status.tweak(wc_rev='3')
    expected_status.tweak('A/D/G/rho', status='  ')

    svntest.actions.run_and_verify_update(wc_dir, expected_output,
                                          expected_disk, expected_status)

    # merge changes from r3:1
    expected_output = svntest.wc.State(wc_dir,
                                       {'A/D/G/rho': Item(status='R ')})
    expected_status.tweak('A/D/G/rho', status='R ', copied='+', wc_rev='-')
    expected_skip = wc.State(wc_dir, {})
    expected_disk.tweak('A/D/G/rho', contents="This is the file 'rho'.\n")
    svntest.actions.run_and_verify_merge(wc_dir, '3', '1', sbox.repo_url,
                                         expected_output, expected_disk,
                                         expected_status, expected_skip)

    # Now revert
    svntest.actions.run_and_verify_svn(None, None, [], 'revert', rho_path)

    # test that rho really was reverted
    expected_status.tweak('A/D/G/rho', copied=None, status='  ', wc_rev=3)
    svntest.actions.run_and_verify_status(wc_dir, expected_status)

    actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 1)
    expected_disk.tweak('A/D/G/rho', contents="new rho\n")
    svntest.tree.compare_trees("disk", actual_disk, expected_disk.old_tree())

    # Make sure the revert removed the copy from information.
    exit_code, output, err = svntest.actions.run_and_verify_svn(
        None, None, [], 'info', rho_path)
    for line in output:
        if line.find("Copied") != -1:
            print("Error: Revert didn't get rid of copy from information")
            raise svntest.Failure
Beispiel #19
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)
Beispiel #20
0
def props_only_file_update(sbox):
    "retranslation occurs on a props-only update"

    sbox.build()
    wc_dir = sbox.wc_dir

    iota_path = os.path.join(wc_dir, 'iota')
    content = [
        "This is the file 'iota'.\n",
        "$Author$\n",
    ]
    content_expanded = [
        "This is the file 'iota'.\n",
        "$Author: jrandom $\n",
    ]

    # Create r2 with iota's contents and svn:keywords modified
    with open(iota_path, 'w') as f:
        f.writelines(content)
    svntest.main.run_svn(None, 'propset', 'svn:keywords', 'Author', iota_path)

    expected_output = wc.State(wc_dir, {
        'iota': Item(verb='Sending'),
    })

    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.tweak('iota', wc_rev=2)

    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status)

    # Create r3 that drops svn:keywords

    # put the content back to its untranslated form
    with open(iota_path, 'w') as f:
        f.writelines(content)

    svntest.main.run_svn(None, 'propdel', 'svn:keywords', iota_path)

    expected_status.tweak('iota', wc_rev=3)

    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status)

    # Now, go back to r2. iota should have the Author keyword expanded.
    expected_disk = svntest.main.greek_state.copy()
    expected_disk.tweak('iota', contents=''.join(content_expanded))

    expected_status = svntest.actions.get_virginal_state(wc_dir, 2)

    svntest.actions.run_and_verify_update(wc_dir, None, None, expected_status,
                                          [], False, wc_dir, '-r', '2')

    if open(iota_path).read() != ''.join(content_expanded):
        raise svntest.Failure("$Author$ is not expanded in 'iota'")

    # Update to r3. this should retranslate iota, dropping the keyword expansion
    expected_disk = svntest.main.greek_state.copy()
    expected_disk.tweak('iota', contents=''.join(content))

    expected_status = svntest.actions.get_virginal_state(wc_dir, 3)

    svntest.actions.run_and_verify_update(wc_dir, None, expected_disk,
                                          expected_status)

    if open(iota_path).read() != ''.join(content):
        raise svntest.Failure("$Author$ is not contracted in 'iota'")

    # We used to leave some temporary files around. Make sure that we don't.
    temps = os.listdir(
        os.path.join(wc_dir, svntest.main.get_admin_name(), 'tmp'))
    if os.path.exists(
            os.path.join(wc_dir, svntest.main.get_admin_name(), 'tmp',
                         'props')):
        temps.remove('prop-base')
        temps.remove('props')
    if temps:
        logger.warn('Temporary files leftover: %s', (', '.join(temps), ))
        raise svntest.Failure
def co_with_obstructing_local_adds(sbox):
    "co handles obstructing paths scheduled for add"

    sbox.build()
    wc_dir = sbox.wc_dir

    # Make a backup copy of the working copy
    wc_backup = sbox.add_wc_path('backup')
    svntest.actions.duplicate_dir(wc_dir, wc_backup)

    # Add files and dirs to the repos via the first WC.  Each of these
    # will be added to the backup WC via a checkout:
    #
    #  A/B/upsilon:   Identical to the file scheduled for addition in
    #                 the backup WC.
    #
    #  A/C/nu:        A "normal" add, won't exist in the backup WC.
    #
    #  A/D/kappa:     Conflicts with the file scheduled for addition in
    #                 the backup WC.
    #
    #  A/D/H/I:       New dirs that will also be scheduled for addition
    #  A/D/H/I/J:     in the backup WC.
    #  A/D/H/I/K:
    #
    #  A/D/H/I/L:     A "normal" dir add, won't exist in the backup WC.
    #
    #  A/D/H/I/K/xi:  Identical to the file scheduled for addition in
    #                 the backup WC.
    #
    #  A/D/H/I/K/eta: Conflicts with the file scheduled for addition in
    #                 the backup WC.
    upsilon_path = os.path.join(wc_dir, 'A', 'B', 'upsilon')
    svntest.main.file_append(upsilon_path, "This is the file 'upsilon'\n")
    nu_path = os.path.join(wc_dir, 'A', 'C', 'nu')
    svntest.main.file_append(nu_path, "This is the file 'nu'\n")
    kappa_path = os.path.join(wc_dir, 'A', 'D', 'kappa')
    svntest.main.file_append(kappa_path, "This is REPOS file 'kappa'\n")
    I_path = os.path.join(wc_dir, 'A', 'D', 'H', 'I')
    os.mkdir(I_path)
    J_path = os.path.join(I_path, 'J')
    os.mkdir(J_path)
    K_path = os.path.join(I_path, 'K')
    os.mkdir(K_path)
    L_path = os.path.join(I_path, 'L')
    os.mkdir(L_path)
    xi_path = os.path.join(K_path, 'xi')
    svntest.main.file_append(xi_path, "This is file 'xi'\n")
    eta_path = os.path.join(K_path, 'eta')
    svntest.main.file_append(eta_path, "This is REPOS file 'eta'\n")
    svntest.main.run_svn(None, 'add', upsilon_path, nu_path, kappa_path,
                         I_path)

    # Created expected output tree for 'svn ci'
    expected_output = wc.State(
        wc_dir, {
            'A/B/upsilon': Item(verb='Adding'),
            'A/C/nu': Item(verb='Adding'),
            'A/D/kappa': Item(verb='Adding'),
            'A/D/H/I': Item(verb='Adding'),
            'A/D/H/I/J': Item(verb='Adding'),
            'A/D/H/I/K': Item(verb='Adding'),
            'A/D/H/I/K/xi': Item(verb='Adding'),
            'A/D/H/I/K/eta': Item(verb='Adding'),
            'A/D/H/I/L': Item(verb='Adding'),
        })

    # Create expected status tree.
    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/B/upsilon': Item(status='  ', wc_rev=2),
        'A/C/nu': Item(status='  ', wc_rev=2),
        'A/D/kappa': Item(status='  ', wc_rev=2),
        'A/D/H/I': Item(status='  ', wc_rev=2),
        'A/D/H/I/J': Item(status='  ', wc_rev=2),
        'A/D/H/I/K': Item(status='  ', wc_rev=2),
        'A/D/H/I/K/xi': Item(status='  ', wc_rev=2),
        'A/D/H/I/K/eta': Item(status='  ', wc_rev=2),
        'A/D/H/I/L': Item(status='  ', wc_rev=2),
    })

    # Commit.
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, wc_dir)

    # Create various paths scheduled for addition which will obstruct
    # the adds coming from the repos.
    upsilon_backup_path = os.path.join(wc_backup, 'A', 'B', 'upsilon')
    svntest.main.file_append(upsilon_backup_path,
                             "This is the file 'upsilon'\n")
    kappa_backup_path = os.path.join(wc_backup, 'A', 'D', 'kappa')
    svntest.main.file_append(kappa_backup_path, "This is WC file 'kappa'\n")
    I_backup_path = os.path.join(wc_backup, 'A', 'D', 'H', 'I')
    os.mkdir(I_backup_path)
    J_backup_path = os.path.join(I_backup_path, 'J')
    os.mkdir(J_backup_path)
    K_backup_path = os.path.join(I_backup_path, 'K')
    os.mkdir(K_backup_path)
    xi_backup_path = os.path.join(K_backup_path, 'xi')
    svntest.main.file_append(xi_backup_path, "This is file 'xi'\n")
    eta_backup_path = os.path.join(K_backup_path, 'eta')
    svntest.main.file_append(eta_backup_path, "This is WC file 'eta'\n")
    svntest.main.run_svn(None, 'add', upsilon_backup_path, kappa_backup_path,
                         I_backup_path)

    # Create expected output tree for a checkout of the wc_backup.
    expected_output = wc.State(
        wc_backup, {
            'A/B/upsilon': Item(status='E '),
            'A/C/nu': Item(status='A '),
            'A/D/H/I': Item(status='E '),
            'A/D/H/I/J': Item(status='E '),
            'A/D/H/I/K': Item(status='E '),
            'A/D/H/I/K/xi': Item(status='E '),
            'A/D/H/I/K/eta': Item(status='C '),
            'A/D/H/I/L': Item(status='A '),
            'A/D/kappa': Item(status='C '),
        })

    # Create expected disk for checkout of wc_backup.
    expected_disk = svntest.main.greek_state.copy()
    expected_disk.add({
        'A/B/upsilon':
        Item("This is the file 'upsilon'\n"),
        'A/C/nu':
        Item("This is the file 'nu'\n"),
        'A/D/H/I':
        Item(),
        'A/D/H/I/J':
        Item(),
        'A/D/H/I/K':
        Item(),
        'A/D/H/I/K/xi':
        Item("This is file 'xi'\n"),
        'A/D/H/I/K/eta':
        Item("\n".join([
            "<<<<<<< .mine", "This is WC file 'eta'", "=======",
            "This is REPOS file 'eta'", ">>>>>>> .r2", ""
        ])),
        'A/D/H/I/L':
        Item(),
        'A/D/kappa':
        Item("\n".join([
            "<<<<<<< .mine", "This is WC file 'kappa'", "=======",
            "This is REPOS file 'kappa'", ">>>>>>> .r2", ""
        ])),
    })

    # Create expected status tree for the checkout.  Since the obstructing
    # kappa and upsilon differ from the repos, they should show as modified.
    expected_status = svntest.actions.get_virginal_state(wc_backup, 2)
    expected_status.add({
        'A/B/upsilon': Item(status='  ', wc_rev=2),
        'A/C/nu': Item(status='  ', wc_rev=2),
        'A/D/H/I': Item(status='  ', wc_rev=2),
        'A/D/H/I/J': Item(status='  ', wc_rev=2),
        'A/D/H/I/K': Item(status='  ', wc_rev=2),
        'A/D/H/I/K/xi': Item(status='  ', wc_rev=2),
        'A/D/H/I/K/eta': Item(status='C ', wc_rev=2),
        'A/D/H/I/L': Item(status='  ', wc_rev=2),
        'A/D/kappa': Item(status='C ', wc_rev=2),
    })

    # "Extra" files that we expect to result from the conflicts.
    extra_files = [
        'eta\.r0', 'eta\.r2', 'eta\.mine', 'kappa\.r0', 'kappa\.r2',
        'kappa\.mine'
    ]

    # Perform the checkout and check the results in three ways.
    # We use --force here because run_and_verify_checkout() will delete
    # wc_backup before performing the checkout otherwise.
    svntest.actions.run_and_verify_checkout(sbox.repo_url, wc_backup,
                                            expected_output, expected_disk,
                                            svntest.tree.detect_conflict_files,
                                            extra_files, None, None, '--force')

    svntest.actions.run_and_verify_status(wc_backup, expected_status)

    # Some obstructions are still not permitted:
    #
    # Test that file and dir obstructions scheduled for addition *with*
    # history fail when checkout tries to add the same path.

    # URL to URL copy of A/D/G to A/D/M.
    G_URL = sbox.repo_url + '/A/D/G'
    M_URL = sbox.repo_url + '/A/D/M'
    svntest.actions.run_and_verify_svn("Copy error:", None, [], 'cp', G_URL,
                                       M_URL, '-m', '')

    # WC to WC copy of A/D/H to A/D/M.  (M is now scheduled for addition
    # with history in WC and pending addition from the repos).
    D_path = os.path.join(wc_dir, 'A', 'D')
    H_path = os.path.join(wc_dir, 'A', 'D', 'H')
    M_path = os.path.join(wc_dir, 'A', 'D', 'M')

    svntest.actions.run_and_verify_svn("Copy error:", None, [], 'cp', H_path,
                                       M_path)

    # URL to URL copy of A/B/E/alpha to A/B/F/omicron.
    omega_URL = sbox.repo_url + '/A/B/E/alpha'
    omicron_URL = sbox.repo_url + '/A/B/F/omicron'
    svntest.actions.run_and_verify_svn("Copy error:", None, [], 'cp',
                                       omega_URL, omicron_URL, '-m', '')

    # WC to WC copy of A/D/H/chi to /A/B/F/omicron.  (omicron is now
    # scheduled for addition with history in WC and pending addition
    # from the repos).
    F_path = os.path.join(wc_dir, 'A', 'B', 'F')
    omicron_path = os.path.join(wc_dir, 'A', 'B', 'F', 'omicron')
    chi_path = os.path.join(wc_dir, 'A', 'D', 'H', 'chi')

    svntest.actions.run_and_verify_svn("Copy error:", None, [], 'cp', chi_path,
                                       omicron_path)

    # Try to co M's Parent.
    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/B/F/omicron':
        Item(status='A ', copied='+', wc_rev='-'),
        'A/B/upsilon':
        Item(status='  ', wc_rev=2),
        'A/C/nu':
        Item(status='  ', wc_rev=2),
        'A/D/kappa':
        Item(status='  ', wc_rev=2),
        'A/D/H/I':
        Item(status='  ', wc_rev=2),
        'A/D/H/I/J':
        Item(status='  ', wc_rev=2),
        'A/D/H/I/K':
        Item(status='  ', wc_rev=2),
        'A/D/H/I/K/xi':
        Item(status='  ', wc_rev=2),
        'A/D/H/I/K/eta':
        Item(status='  ', wc_rev=2),
        'A/D/H/I/L':
        Item(status='  ', wc_rev=2),
        'A/D/M':
        Item(status='A ', copied='+', wc_rev='-'),
        'A/D/M/psi':
        Item(status='  ', copied='+', wc_rev='-'),
        'A/D/M/chi':
        Item(status='  ', copied='+', wc_rev='-'),
        'A/D/M/omega':
        Item(status='  ', copied='+', wc_rev='-'),
        'A/D/M/I':
        Item(status='A ', copied='+', wc_rev='-',
             entry_status='  '),  # A/D/MI is a new op_root
        'A/D/M/I/J':
        Item(status='  ', copied='+', wc_rev='-'),
        'A/D/M/I/K':
        Item(status='  ', copied='+', wc_rev='-'),
        'A/D/M/I/K/xi':
        Item(status='  ', copied='+', wc_rev='-'),
        'A/D/M/I/K/eta':
        Item(status='  ', copied='+', wc_rev='-'),
        'A/D/M/I/L':
        Item(status='  ', copied='+', wc_rev='-'),
    })
    svntest.actions.run_and_verify_status(wc_dir, expected_status)

    expected_output = wc.State(
        wc_dir, {
            'A/D/M': Item(status='  ', treeconflict='C'),
            'A/D/M/rho': Item(status='  ', treeconflict='A'),
            'A/D/M/pi': Item(status='  ', treeconflict='A'),
            'A/D/M/tau': Item(status='  ', treeconflict='A'),
        })
    expected_disk = wc.State(
        '', {
            'gamma': Item("This is the file 'gamma'.\n"),
            'G/pi': Item("This is the file 'pi'.\n"),
            'G/rho': Item("This is the file 'rho'.\n"),
            'G/tau': Item("This is the file 'tau'.\n"),
            'H/I': Item(),
            'H/I/J': Item(),
            'H/I/K': Item(),
            'H/I/K/xi': Item("This is file 'xi'\n"),
            'H/I/K/eta': Item("This is REPOS file 'eta'\n"),
            'H/I/L': Item(),
            'H/chi': Item("This is the file 'chi'.\n"),
            'H/psi': Item("This is the file 'psi'.\n"),
            'H/omega': Item("This is the file 'omega'.\n"),
            'M/I': Item(),
            'M/I/J': Item(),
            'M/I/K': Item(),
            'M/I/K/xi': Item("This is file 'xi'\n"),
            'M/I/K/eta': Item("This is REPOS file 'eta'\n"),
            'M/I/L': Item(),
            'M/chi': Item("This is the file 'chi'.\n"),
            'M/psi': Item("This is the file 'psi'.\n"),
            'M/omega': Item("This is the file 'omega'.\n"),
            'kappa': Item("This is REPOS file 'kappa'\n"),
        })
    svntest.actions.run_and_verify_checkout(sbox.repo_url + '/A/D', D_path,
                                            expected_output, expected_disk,
                                            None, None, None, None, '--force')

    expected_status.tweak('A/D/M', treeconflict='C', status='R ')
    expected_status.tweak('A/D',
                          'A/D/G',
                          'A/D/G/pi',
                          'A/D/G/rho',
                          'A/D/G/tau',
                          'A/D/gamma',
                          'A/D/kappa',
                          'A/D/H',
                          'A/D/H/I',
                          'A/D/H/I/J',
                          'A/D/H/I/K',
                          'A/D/H/I/K/xi',
                          'A/D/H/I/K/eta',
                          'A/D/H/I/L',
                          wc_rev=4)
    expected_status.add({
        'A/D/H/chi': Item(status='  ', wc_rev=4),
        'A/D/H/psi': Item(status='  ', wc_rev=4),
        'A/D/H/omega': Item(status='  ', wc_rev=4),
        'A/D/M/pi': Item(status='D ', wc_rev=4),
        'A/D/M/rho': Item(status='D ', wc_rev=4),
        'A/D/M/tau': Item(status='D ', wc_rev=4),
    })
    svntest.actions.run_and_verify_status(wc_dir, expected_status)

    # Try to co omicron's parent.
    expected_output = wc.State(
        wc_dir, {
            'A/B/F/omicron': Item(status='  ', treeconflict='C'),
        })
    expected_disk = wc.State('', {
        'omicron': Item("This is the file 'chi'.\n"),
    })
    svntest.actions.run_and_verify_checkout(sbox.repo_url + '/A/B/F', F_path,
                                            expected_output, expected_disk,
                                            None, None, None, None, '--force')

    expected_status.tweak('A/B/F/omicron', treeconflict='C', status='R ')
    expected_status.add({
        'A/B/F': Item(status='  ', wc_rev=4),
    })
    svntest.actions.run_and_verify_status(wc_dir, expected_status)
Beispiel #22
0
def svnauthz_accessof_is_repo_test(sbox):
    "test 'svnauthz accessof --is' on files and urls"

    sbox.build()
    wc_dir = sbox.wc_dir
    repo_url = sbox.repo_url

    authz_content = "[/]\ngroucho = \ngallagher = rw\n* = r\n" + \
        "[/bios]\n* = rw\n" + \
        "[comedy:/jokes]\ngroucho = rw\n" + \
        "[slapstick:/jokes]\n* =\n"

    # build an authz file and commit it to the repo
    authz_path = os.path.join(wc_dir, 'A', 'authz')
    svntest.main.file_write(authz_path, authz_content)
    svntest.main.run_svn(None, 'add', authz_path)
    expected_output = wc.State(wc_dir, {'A/authz': Item(verb='Adding')})
    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/authz': Item(status='  ', wc_rev=2),
    })
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status)

    # Test an invalid --is option, should get an error message and exit code
    # of 2.
    authz_url = repo_url + "/A/authz"
    expected_output = svntest.verify.RegexOutput(
        ".*'x' is not a valid argument for --is", match_all=False)
    svntest.actions.run_and_verify_svnauthz(None, expected_output, 2, False,
                                            "accessof", authz_url, "--is", "x")

    # Anonymous access with no path, and no repository should be rw
    # since it returns the highest level of access granted anywhere.
    # So /bios being rw for everyone means this will be rw.
    # Test --is rw returns 0.
    svntest.actions.run_and_verify_svnauthz(None, None, 0, False, "accessof",
                                            authz_url, "--is", "rw")
    # Test --is r returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--is", "r")
    # Test --is no returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--is", "no")

    # Anonymous access on /jokes should be r, no repo so won't match
    # the slapstick:/jokes section.
    # Test --is r returns 0.
    svntest.actions.run_and_verify_svnauthz(None, None, 0, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--is", "r")
    # Test --is rw returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--is", "rw")
    # Test --is no returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--is", "no")

    # Anonymous access on /jokes on slapstick repo should be no
    # Test --is no returns 0.
    svntest.actions.run_and_verify_svnauthz(None, None, 0, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--repository", "slapstick",
                                            "--is", "no")
    # Test --is rw returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--repository", "slapstick",
                                            "--is", "rw")
    # Test --is r returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--repository", "slapstick",
                                            "--is", "r")

    # User access with no path, and no repository should be rw
    # since it returns the h ighest level of access anywhere.
    # So /bios being rw for everyone means this will be rw.
    # Test --is rw returns 0.
    svntest.actions.run_and_verify_svnauthz(None, None, 0, False, "accessof",
                                            authz_url, "--username", "groucho",
                                            "--is", "rw")
    # Test --is r returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--username", "groucho",
                                            "--is", "r")
    # Test --is no returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--username", "groucho",
                                            "--is", "no")

    # User groucho specified on /jokes with no repo, will not match any of the
    # repo specific sections, so is r since everyone has read access.
    # Test --is r returns 0.
    svntest.actions.run_and_verify_svnauthz(None, None, 0, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--username", "groucho", "--is",
                                            "r")
    # Test --is rw returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--username", "groucho", "--is",
                                            "rw")
    # Test --is no returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--username", "groucho", "--is",
                                            "no")

    # User groucho specified on /jokes with the repo comedy will be rw
    # Test --is rw returns 0.
    svntest.actions.run_and_verify_svnauthz(None, None, 0, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--username", "groucho",
                                            "--repository", "comedy", "--is",
                                            "rw")
    # Test --is r returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--username", "groucho",
                                            "--repository", "comedy", "--is",
                                            "r")
    # Test --is no returns 3.
    svntest.actions.run_and_verify_svnauthz(None, None, 3, False, "accessof",
                                            authz_url, "--path", "/jokes",
                                            "--username", "groucho",
                                            "--repository", "comedy", "--is",
                                            "no")

    # Add an invalid line to the authz file
    svntest.main.file_append(authz_path, "x\n")
    expected_output = wc.State(wc_dir, {'A/authz': Item(verb='Sending')})
    expected_status.tweak('A/authz', wc_rev=3)
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status)

    # Check that --is returns 1 when the syntax is invalid with a url.
    expected_out = svntest.verify.RegexOutput(
        ".*Error while parsing config file:", match_all=False)
    svntest.actions.run_and_verify_svnauthz(None, expected_out, 1, False,
                                            "accessof", authz_url, "--path",
                                            "/jokes", "--username", "groucho",
                                            "--repository", "comedy", "--is",
                                            "rw")
Beispiel #23
0
def revert_replaced_with_history_file_1(sbox):
    "revert a committed replace-with-history == no-op"

    sbox.build()
    wc_dir = sbox.wc_dir
    iota_path = os.path.join(wc_dir, 'iota')
    mu_path = os.path.join(wc_dir, 'A', 'mu')

    # Remember the original text of 'mu'
    exit_code, text_r1, err = svntest.actions.run_and_verify_svn(
        None, None, [], 'cat', mu_path)
    # delete mu and replace it with a copy of iota
    svntest.main.run_svn(None, 'rm', mu_path)
    svntest.main.run_svn(None, 'mv', iota_path, mu_path)

    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.tweak('A/mu', status='  ', wc_rev=2)
    expected_status.remove('iota')
    expected_output = svntest.wc.State(wc_dir, {
        'iota': Item(verb='Deleting'),
        'A/mu': Item(verb='Replacing'),
    })
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, wc_dir)

    # update the working copy
    svntest.main.run_svn(None, 'up', wc_dir)

    # now revert back to the state in r1
    expected_output = svntest.wc.State(wc_dir, {
        'A/mu': Item(status='R '),
        'iota': Item(status='A ')
    })
    expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
    expected_status.tweak('A/mu', status='R ', copied='+', wc_rev='-')
    expected_status.tweak('iota', status='A ', copied='+', wc_rev='-')
    expected_skip = wc.State(wc_dir, {})
    expected_disk = svntest.main.greek_state.copy()
    svntest.actions.run_and_verify_merge(wc_dir, '2', '1', sbox.repo_url,
                                         expected_output, expected_disk,
                                         expected_status, expected_skip)

    # and commit in r3
    expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
    expected_status.tweak('A/mu', status='  ', wc_rev=3)
    expected_status.tweak('iota', status='  ', wc_rev=3)
    expected_output = svntest.wc.State(wc_dir, {
        'iota': Item(verb='Adding'),
        'A/mu': Item(verb='Replacing'),
    })
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, wc_dir)

    # Verify the content of 'mu'
    svntest.actions.run_and_verify_svn(None, text_r1, [], 'cat', mu_path)

    # situation: no local modifications, mu has its original content again.

    # revert 'mu' locally, shouldn't change a thing.
    svntest.actions.run_and_verify_svn(None, [], [], "revert", mu_path)

    # Verify the content of 'mu'
    svntest.actions.run_and_verify_svn(None, text_r1, [], 'cat', mu_path)
Beispiel #24
0
def status_of_missing_dir_after_revert_replaced_with_history_dir(sbox):
    "status after replace+, revert, and local rm"

    sbox.build()
    wc_dir = sbox.wc_dir
    repo_url = sbox.repo_url

    # delete A/D/G and commit
    G_path = os.path.join(wc_dir, "A", "D", "G")
    svntest.actions.run_and_verify_svn(None, None, [], "rm", G_path)
    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.remove('A/D/G', 'A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau')
    expected_output = svntest.wc.State(wc_dir, {
        'A/D/G': Item(verb='Deleting'),
    })
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, wc_dir)

    # copy A/D/G from A/B/E and commit
    E_path = os.path.join(wc_dir, "A", "B", "E")
    svntest.actions.run_and_verify_svn(None, None, [], "cp", E_path, G_path)
    expected_status.add({
        'A/D/G': Item(status='  ', wc_rev='3'),
        'A/D/G/alpha': Item(status='  ', wc_rev='3'),
        'A/D/G/beta': Item(status='  ', wc_rev='3')
    })
    expected_output = svntest.wc.State(wc_dir, {
        'A/D/G': Item(verb='Adding'),
    })
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status, None, wc_dir)

    # update the working copy
    svntest.main.run_svn(None, 'up', wc_dir)

    # now rollback to r1, thereby reinstating the old 'G'
    ### Eventually, expected output for 'A/D/G' should be 'R '
    ### (replaced) instead of 'A ' (added).  See issue #571 for details.
    expected_output = svntest.wc.State(
        wc_dir, {
            'A/D/G': Item(status='R '),
            'A/D/G/rho': Item(status='A '),
            'A/D/G/pi': Item(status='A '),
            'A/D/G/tau': Item(status='A '),
        })
    expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
    expected_status.tweak('A/D/G', status='R ', copied='+', wc_rev='-')
    expected_status.tweak('A/D/G/rho', status='A ', copied='+', wc_rev='-')
    expected_status.tweak('A/D/G/pi', status='A ', copied='+', wc_rev='-')
    expected_status.tweak('A/D/G/tau', status='A ', copied='+', wc_rev='-')
    expected_status.add({
        'A/D/G/alpha':
        Item(status='D ', copied='+', wc_rev='-'),
        'A/D/G/beta':
        Item(status='D ', copied='+', wc_rev='-')
    })
    expected_skip = wc.State(wc_dir, {})
    expected_disk = svntest.main.greek_state.copy()
    svntest.actions.run_and_verify_merge(wc_dir,
                                         '3',
                                         '1',
                                         sbox.repo_url,
                                         expected_output,
                                         expected_disk,
                                         expected_status,
                                         expected_skip,
                                         dry_run=0)

    # now test if the revert works ok
    expected_output = svntest.verify.UnorderedOutput([
        "Reverted '" + G_path + "'\n",
        "Reverted '" + os.path.join(G_path, 'pi') + "'\n",
        "Reverted '" + os.path.join(G_path, 'rho') + "'\n",
        "Reverted '" + os.path.join(G_path, 'tau') + "'\n",
        "Reverted '" + os.path.join(G_path, 'alpha') + "'\n",
        "Reverted '" + os.path.join(G_path, 'beta') + "'\n"
    ])

    svntest.actions.run_and_verify_svn(None, expected_output, [], "revert",
                                       "-R", G_path)

    expected_output = svntest.verify.UnorderedOutput([
        "?       " + os.path.join(G_path, "pi") + "\n",
        "?       " + os.path.join(G_path, "rho") + "\n",
        "?       " + os.path.join(G_path, "tau") + "\n"
    ])
    svntest.actions.run_and_verify_svn(None, expected_output, [], "status",
                                       wc_dir)

    svntest.main.safe_rmtree(G_path)

    expected_output = svntest.verify.UnorderedOutput(
        ["!       " + G_path + "\n"])
    svntest.actions.run_and_verify_svn(None, expected_output, [], "status",
                                       wc_dir)
def make_local_tree(sbox, mod_files=False, add_unversioned=False):
    """Make a local unversioned tree to checkout into."""

    sbox.build(create_wc=False)

    if os.path.exists(sbox.wc_dir):
        svntest.main.safe_rmtree(sbox.wc_dir)

    export_target = sbox.wc_dir
    expected_output = svntest.main.greek_state.copy()
    expected_output.wc_dir = sbox.wc_dir
    expected_output.desc[""] = Item()
    expected_output.tweak(contents=None, status="A ")

    # Export an unversioned tree to sbox.wc_dir.
    svntest.actions.run_and_verify_export(sbox.repo_url, export_target,
                                          expected_output,
                                          svntest.main.greek_state.copy())

    # Remove everything remaining except for 'iota', 'A/', and 'A/mu'.
    svntest.main.safe_rmtree(os.path.join(sbox.wc_dir, "A", "B"))
    svntest.main.safe_rmtree(os.path.join(sbox.wc_dir, "A", "C"))
    svntest.main.safe_rmtree(os.path.join(sbox.wc_dir, "A", "D"))

    # Should obstructions differ from the standard greek tree?
    if mod_files:
        iota_path = os.path.join(sbox.wc_dir, "iota")
        mu_path = os.path.join(sbox.wc_dir, "A", "mu")
        svntest.main.file_write(
            iota_path, "This is the local version of the file 'iota'.\n")
        svntest.main.file_write(
            mu_path, "This is the local version of the file 'mu'.\n")

    # Add some files that won't obstruct anything in standard greek tree?
    if add_unversioned:
        sigma_path = os.path.join(sbox.wc_dir, "sigma")
        svntest.main.file_append(sigma_path, "unversioned sigma")
        upsilon_path = os.path.join(sbox.wc_dir, "A", "upsilon")
        svntest.main.file_append(upsilon_path, "unversioned upsilon")
        Z_path = os.path.join(sbox.wc_dir, "A", "Z")
        os.mkdir(Z_path)

    return wc.State(
        sbox.wc_dir,
        {
            "A": Item(status='E '),  # Obstruction
            "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 '),
            "A/mu": Item(status='E '),  # Obstruction
            "A/C": Item(status='A '),
            "A/D": Item(status='A '),
            "A/D/gamma": Item(status='A '),
            "A/D/G": Item(status='A '),
            "A/D/G/pi": Item(status='A '),
            "A/D/G/rho": Item(status='A '),
            "A/D/G/tau": Item(status='A '),
            "A/D/H": Item(status='A '),
            "A/D/H/chi": Item(status='A '),
            "A/D/H/omega": Item(status='A '),
            "A/D/H/psi": Item(status='A '),
            "iota": Item(status='E '),  # Obstruction
        })
def deep_trees_skipping_on_update(sbox, test_case, skip_paths,
                                  chdir_skip_paths):
    """
  Create tree conflicts, then update again, expecting the existing tree
  conflicts to be skipped.
  SKIP_PATHS is a list of paths, relative to the "base dir", for which
  "update" on the "base dir" should report as skipped.
  CHDIR_SKIP_PATHS is a list of (target-path, skipped-path) pairs for which
  an update of "target-path" (relative to the "base dir") should result in
  "skipped-path" (relative to "target-path") being reported as skipped.
  """
    """FURTHER_ACTION is a function that will make a further modification to
  each target, this being the modification that we expect to be skipped. The
  function takes the "base dir" (the WC path to the test case directory) as
  its only argument."""
    further_action = deep_trees_tree_del_repos

    j = os.path.join
    wc_dir = sbox.wc_dir
    base = j(wc_dir, test_case.name)

    # Initialize: generate conflicts. (We do not check anything here.)
    setup_case = DeepTreesTestCase(test_case.name, test_case.local_action,
                                   test_case.incoming_action, None, None, None)
    deep_trees_run_tests_scheme_for_update(sbox, [setup_case])

    # Make a further change to each target in the repository so there is a new
    # revision to update to. (This is r4.)
    further_action(sbox.repo_url + '/' + test_case.name)

    # Update whole working copy, expecting the nodes still in conflict to be
    # skipped.

    x_out = test_case.expected_output
    if x_out != None:
        x_out = x_out.copy()
        x_out.wc_dir = base

    x_disk = test_case.expected_disk

    x_status = test_case.expected_status
    if x_status != None:
        x_status = x_status.copy()
        x_status.wc_dir = base
        # Account for nodes that were updated by further_action
        x_status.tweak('', 'D', 'F', 'DD', 'DF', 'DDD', 'DDF', wc_rev=4)

    if test_case.error_re_string == None:
        expected_stderr = []
    else:
        expected_stderr = test_case.error_re_string

    run_and_verify_update(base,
                          x_out,
                          x_disk,
                          None,
                          expected_stderr=expected_stderr)

    run_and_verify_unquiet_status(base, x_status)

    # Try to update each in-conflict subtree. Expect a 'Skipped' output for
    # each, and the WC status to be unchanged.
    for path in skip_paths:
        run_and_verify_update(j(base, path),
                              wc.State(base, {path: Item(verb='Skipped')}),
                              None, None)

    run_and_verify_unquiet_status(base, x_status)

    # Try to update each in-conflict subtree. Expect a 'Skipped' output for
    # each, and the WC status to be unchanged.
    # This time, cd to the subdir before updating it.
    was_cwd = os.getcwd()
    for path, skipped in chdir_skip_paths:
        if isinstance(skipped, list):
            expected_skip = {}
            for p in skipped:
                expected_skip[p] = Item(verb='Skipped')
        else:
            expected_skip = {skipped: Item(verb='Skipped')}
        p = j(base, path)
        run_and_verify_update(p, wc.State(p, expected_skip), None, None)
    os.chdir(was_cwd)

    run_and_verify_unquiet_status(base, x_status)

    # Verify that commit still fails.
    for path, skipped in chdir_skip_paths:

        run_and_verify_commit(j(base, path), None, None,
                              test_case.commit_block_string, base)

    run_and_verify_unquiet_status(base, x_status)
Beispiel #27
0
def svnauthz_accessof_groups_repo_test(sbox):
    "test 'svnauthz accessof --groups-file' on urls"

    sbox.build()
    wc_dir = sbox.wc_dir
    repo_url = sbox.repo_url

    authz_content = "[/]\n@musicians = rw\n@comedians = \n" + \
        "[comedy:/jokes]\n@musicians = \n@comedians = r\n"

    groups_content = "[groups]\nmusicians=stafford\ncomedians=groucho\n"

    # build authz and groups files and commit them to the repo
    authz_path = os.path.join(wc_dir, 'A', 'authz')
    groups_path = os.path.join(wc_dir, 'A', 'groups')
    svntest.main.file_write(authz_path, authz_content)
    svntest.main.file_write(groups_path, groups_content)
    svntest.main.run_svn(None, 'add', authz_path, groups_path)
    expected_output = wc.State(wc_dir, {
        'A/authz': Item(verb='Adding'),
        'A/groups': Item(verb='Adding'),
    })
    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/authz': Item(status='  ', wc_rev=2),
        'A/groups': Item(status='  ', wc_rev=2),
    })

    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status)

    # Anonymous access with no path, and no repository should be no
    # since it returns the highest level of access granted anywhere.
    authz_url = repo_url + "/A/authz"
    groups_url = repo_url + "/A/groups"
    svntest.actions.run_and_verify_svnauthz(["no\n"], None, 0, False,
                                            "accessof", authz_url,
                                            "--groups-file", groups_url)

    # User stafford (@musicians) access with no path, and no repository should
    # be no since it returns the highest level of access granted anywhere.
    svntest.actions.run_and_verify_svnauthz(["rw\n"], None, 0, False,
                                            "accessof", authz_url,
                                            "--groups-file", groups_url,
                                            "--username", "stafford")

    # User groucho (@comedians) access with no path, and no repository should
    # be no since it returns the highest level of access granted anywhere.
    svntest.actions.run_and_verify_svnauthz(["no\n"], None, 0, False,
                                            "accessof", authz_url,
                                            "--groups-file", groups_url,
                                            "--username", "groucho")

    # Anonymous access specified on /jokes with the repo comedy will be no.
    svntest.actions.run_and_verify_svnauthz(["no\n"], None, 0, False,
                                            "accessof", authz_url,
                                            "--groups-file", groups_url,
                                            "--path", "jokes", "--repository",
                                            "comedy")

    # User stafford (@musicians) specified on /jokes with the repo comedy
    # will be no.
    svntest.actions.run_and_verify_svnauthz(["no\n"], None, 0, False,
                                            "accessof", authz_url,
                                            "--groups-file", groups_url,
                                            "--path", "jokes", "--repository",
                                            "comedy", "--username", "stafford")

    # User groucho (@comedians) specified on /jokes with the repo
    # comedy will be r.
    svntest.actions.run_and_verify_svnauthz(["r\n"], None, 0, False,
                                            "accessof", authz_url,
                                            "--groups-file", groups_url,
                                            "--path", "jokes", "--repository",
                                            "comedy", "--username", "groucho")
Beispiel #28
0
def merge_fails_if_subtree_is_deleted_on_src(sbox):
  "merge fails if subtree is deleted on src"

  ## See https://issues.apache.org/jira/browse/SVN-2876. ##

  # Create a WC
  sbox.build()
  wc_dir = sbox.wc_dir

  if is_ra_type_svn() or is_ra_type_dav():
    write_authz_file(sbox, {"/" : "* = rw",
                            "/unrelated" : ("* =\n" +
                             svntest.main.wc_author2 + " = rw")})

  # Some paths we'll care about
  Acopy_path = sbox.ospath('A_copy')
  gamma_path = sbox.ospath('A/D/gamma')
  Acopy_gamma_path = sbox.ospath('A_copy/D/gamma')
  Acopy_D_path = sbox.ospath('A_copy/D')
  A_url = sbox.repo_url + '/A'
  Acopy_url = sbox.repo_url + '/A_copy'

  # Contents to be added to 'gamma'
  new_content = "line1\nline2\nline3\nline4\nline5\n"

  svntest.main.file_write(gamma_path, new_content)

  # Create expected output tree for commit
  expected_output = wc.State(wc_dir, {
    'A/D/gamma' : Item(verb='Sending'),
    })

  # Create expected status tree for commit
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
  expected_status.tweak('A/D/gamma', wc_rev=2)

  # Commit the new content
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        expected_status)

  svntest.actions.run_and_verify_svn(None, [], 'cp', A_url, Acopy_url,
                                     '-m', 'create a new copy of A')

  # Update working copy
  svntest.actions.run_and_verify_svn(None, [], 'up', wc_dir)

  svntest.main.file_substitute(gamma_path, "line1", "this is line1")
  # Create expected output tree for commit
  expected_output = wc.State(wc_dir, {
    'A/D/gamma' : Item(verb='Sending'),
    })

  # Create expected status tree for commit
  expected_status.tweak(wc_rev=3)
  expected_status.tweak('A/D/gamma', wc_rev=4)
  expected_status.add({
    'A_copy'          : Item(status='  ', wc_rev=3),
    'A_copy/B'        : Item(status='  ', wc_rev=3),
    'A_copy/B/lambda' : Item(status='  ', wc_rev=3),
    'A_copy/B/E'      : Item(status='  ', wc_rev=3),
    'A_copy/B/E/alpha': Item(status='  ', wc_rev=3),
    'A_copy/B/E/beta' : Item(status='  ', wc_rev=3),
    'A_copy/B/F'      : Item(status='  ', wc_rev=3),
    'A_copy/mu'       : Item(status='  ', wc_rev=3),
    'A_copy/C'        : Item(status='  ', wc_rev=3),
    'A_copy/D'        : Item(status='  ', wc_rev=3),
    'A_copy/D/gamma'  : Item(status='  ', wc_rev=3),
    'A_copy/D/G'      : Item(status='  ', wc_rev=3),
    'A_copy/D/G/pi'   : Item(status='  ', wc_rev=3),
    'A_copy/D/G/rho'  : Item(status='  ', wc_rev=3),
    'A_copy/D/G/tau'  : Item(status='  ', wc_rev=3),
    'A_copy/D/H'      : Item(status='  ', wc_rev=3),
    'A_copy/D/H/chi'  : Item(status='  ', wc_rev=3),
    'A_copy/D/H/omega': Item(status='  ', wc_rev=3),
    'A_copy/D/H/psi'  : Item(status='  ', wc_rev=3),
    })

  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                        expected_status)

  # Delete A/D/gamma from working copy
  svntest.actions.run_and_verify_svn(None, [], 'delete', gamma_path)
  # Create expected output tree for commit
  expected_output = wc.State(wc_dir, {
    'A/D/gamma' : Item(verb='Deleting'),
    })

  expected_status.remove('A/D/gamma')

  svntest.actions.run_and_verify_commit(wc_dir,
                                        expected_output,
                                        expected_status,
                                        [],
                                        wc_dir, wc_dir)
  svntest.actions.run_and_verify_svn(
    expected_merge_output([[3,4]],
                          ['U    ' + Acopy_gamma_path + '\n',
                           ' U   ' + Acopy_gamma_path + '\n']),
    [], 'merge', '-r1:4',
    A_url + '/D/gamma' + '@4',
    Acopy_gamma_path)

  # r6: create an empty (unreadable) commit.
  # Empty or unreadable revisions used to crash a svn 1.6+ client when
  # used with a 1.5 server:
  # http://svn.haxx.se/dev/archive-2009-04/0476.shtml
  svntest.main.run_svn(None, 'mkdir', sbox.repo_url + '/unrelated',
                       '--username', svntest.main.wc_author2,
                       '-m', 'creating a rev with no paths.')

  # A delete merged ontop of a modified file is normally a tree conflict,
  # see notes/tree-conflicts/detection.txt, but --force currently avoids
  # this.
  svntest.actions.run_and_verify_svn(
    expected_merge_output([[3,6]],
                          ['D    ' + Acopy_gamma_path + '\n',
                           ' U   ' + Acopy_path + '\n']),
    [], 'merge', '-r1:6', '--force',
    A_url, Acopy_path)
Beispiel #29
0
def svnauthz_accessof_txn_test(sbox):
    "test 'svnauthz accessof --transaction'"

    sbox.build()
    wc_dir = sbox.wc_dir
    repo_dir = sbox.repo_dir

    logfilepath = os.path.join(repo_dir, 'hooks.log')
    pre_commit_hook = svntest.main.get_pre_commit_hook_path(repo_dir)
    hook_instance = hook_template % (repr(
        svntest.main.svnauthz_binary), repr([('accessof', '--is rw A/authz')]))
    svntest.main.create_python_hook_script(pre_commit_hook, hook_instance)

    # Create an authz file
    authz_content = "[/]\n* = rw\n"
    authz_path = os.path.join(wc_dir, 'A/authz')
    svntest.main.file_write(authz_path, authz_content)
    svntest.main.run_svn(None, 'add', authz_path)

    # Only really testing the exit value code paths.

    # commit a valid authz file, and run --is rw which is true.
    # Should get an exit of 0.
    expected_output = wc.State(wc_dir, {'A/authz': Item(verb='Adding')})
    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/authz': Item(status='  ', wc_rev=2),
    })
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status)
    expected_data = ['Exit 0\n']
    verify_logfile(logfilepath, expected_data)

    # commit a valid authz file, and run --is r which is false
    # Should get an exit of 3.
    hook_instance = hook_template % (repr(
        svntest.main.svnauthz_binary), repr([('accessof', '--is r A/authz')]))
    svntest.main.create_python_hook_script(pre_commit_hook, hook_instance)
    expected_output = wc.State(wc_dir, {'A/authz': Item(verb='Sending')})
    expected_status.tweak('A/authz', status='  ', wc_rev=3)
    svntest.main.file_append(authz_path, "groucho = r\n")
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status)
    expected_data = svntest.verify.ExpectedOutput('Exit 3\n', match_all=False)
    verify_logfile(logfilepath, expected_data)

    # break the authz file with a non-existent group and check for an exit 1.
    expected_status.tweak('A/authz', status='  ', wc_rev=4)
    svntest.main.file_append(authz_path, "@friends = rw\n")
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status)
    expected_data = svntest.verify.ExpectedOutput('Exit 1\n', match_all=False)
    verify_logfile(logfilepath, expected_data)

    # break the authz file with a non-existent gropu and check for an exit 2.
    expected_output = wc.State(wc_dir, {'A/authz': Item(verb='Deleting')})
    expected_status.remove('A/authz')
    svntest.main.run_svn(None, 'rm', authz_path)
    svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                          expected_status)
    expected_data = svntest.verify.ExpectedOutput('Exit 2\n', match_all=False)
    verify_logfile(logfilepath, expected_data)

Item = wc.StateItem

# initial deep trees state
deep_trees_virginal_state = wc.State(
    '', {
        'F': Item(),
        'F/alpha': Item("This is the file 'alpha'.\n"),
        'D': Item(),
        'D/D1': Item(),
        'DF': Item(),
        'DF/D1': Item(),
        'DF/D1/beta': Item("This is the file 'beta'.\n"),
        'DD': Item(),
        'DD/D1': Item(),
        'DD/D1/D2': Item(),
        'DDF': Item(),
        'DDF/D1': Item(),
        'DDF/D1/D2': Item(),
        'DDF/D1/D2/gamma': Item("This is the file 'gamma'.\n"),
        'DDD': Item(),
        'DDD/D1': Item(),
        'DDD/D1/D2': Item(),
        'DDD/D1/D2/D3': Item(),
    })

# Many actions on deep trees and their resulting states...


def deep_trees_leaf_edit(base):