def deep_trees_tree_del(base):
    """Helper function for deep trees test cases.  Delete top-level dirs."""
    j = os.path.join
    F = j(base, 'F', 'alpha')
    D = j(base, 'D', 'D1')
    DF = j(base, 'DF', 'D1')
    DD = j(base, 'DD', 'D1')
    DDF = j(base, 'DDF', 'D1')
    DDD = j(base, 'DDD', 'D1')
    main.run_svn(None, 'rm', F, D, DF, DD, DDF, DDD)
Exemplo n.º 2
0
def deep_trees_tree_del(base):
  """Helper function for deep trees test cases.  Delete top-level dirs."""
  j = os.path.join
  F   = j(base, 'F', 'alpha')
  D   = j(base, 'D', 'D1')
  DF  = j(base, 'DF', 'D1')
  DD  = j(base, 'DD', 'D1')
  DDF = j(base, 'DDF', 'D1')
  DDD = j(base, 'DDD', 'D1')
  main.run_svn(None, 'rm', F, D, DF, DD, DDF, DDD)
Exemplo n.º 3
0
def deep_trees_tree_del_repos(base):
  """Helper function for deep trees test cases.  Delete top-level dirs,
  directly in the repository."""
  j = '/'.join
  F   = j([base, 'F', 'alpha'])
  D   = j([base, 'D', 'D1'])
  DF  = j([base, 'DF', 'D1'])
  DD  = j([base, 'DD', 'D1'])
  DDF = j([base, 'DDF', 'D1'])
  DDD = j([base, 'DDD', 'D1'])
  main.run_svn(None, 'mkdir', '-m', '', F, D, DF, DD, DDF, DDD)
def deep_trees_leaf_del(base):
    """Helper function for deep trees test cases. Delete files and empty
  dirs."""
    j = os.path.join
    F = j(base, 'F', 'alpha')
    D = j(base, 'D', 'D1')
    DF = j(base, 'DF', 'D1', 'beta')
    DD = j(base, 'DD', 'D1', 'D2')
    DDF = j(base, 'DDF', 'D1', 'D2', 'gamma')
    DDD = j(base, 'DDD', 'D1', 'D2', 'D3')
    main.run_svn(None, 'rm', F, D, DF, DD, DDF, DDD)
def deep_trees_tree_del_repos(base):
    """Helper function for deep trees test cases.  Delete top-level dirs,
  directly in the repository."""
    j = '/'.join
    F = j([base, 'F', 'alpha'])
    D = j([base, 'D', 'D1'])
    DF = j([base, 'DF', 'D1'])
    DD = j([base, 'DD', 'D1'])
    DDF = j([base, 'DDF', 'D1'])
    DDD = j([base, 'DDD', 'D1'])
    main.run_svn(None, 'mkdir', '-m', '', F, D, DF, DD, DDF, DDD)
Exemplo n.º 6
0
def deep_trees_leaf_del(base):
  """Helper function for deep trees test cases. Delete files and empty
  dirs."""
  j = os.path.join
  F   = j(base, 'F', 'alpha')
  D   = j(base, 'D', 'D1')
  DF  = j(base, 'DF', 'D1', 'beta')
  DD  = j(base, 'DD', 'D1', 'D2')
  DDF = j(base, 'DDF', 'D1', 'D2', 'gamma')
  DDD = j(base, 'DDD', 'D1', 'D2', 'D3')
  main.run_svn(None, 'rm', F, D, DF, DD, DDF, DDD)
def add_deep_trees(sbox, base_dir_name):
    """Prepare a "deep_trees" within a given directory.

  The directory <sbox.wc_dir>/<base_dir_name> is created and a deep_tree
  is created within. The items are only added, a commit has to be
  called separately, if needed.

  <base_dir_name> will thus be a container for the set of containers
  mentioned in make_deep_trees().
  """
    j = os.path.join
    base = j(sbox.wc_dir, base_dir_name)
    make_deep_trees(base)
    main.run_svn(None, 'add', base)
Exemplo n.º 8
0
def add_deep_trees(sbox, base_dir_name):
  """Prepare a "deep_trees" within a given directory.

  The directory <sbox.wc_dir>/<base_dir_name> is created and a deep_tree
  is created within. The items are only added, a commit has to be
  called separately, if needed.

  <base_dir_name> will thus be a container for the set of containers
  mentioned in make_deep_trees().
  """
  j = os.path.join
  base = j(sbox.wc_dir, base_dir_name)
  make_deep_trees(base)
  main.run_svn(None, 'add', base)
Exemplo n.º 9
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
Exemplo n.º 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
Exemplo n.º 11
0
def set_up_repos(wc_dir, br_dir, scenarios):

  if not os.path.exists(br_dir):
    main.run_svn(None, "mkdir", "--parents", br_dir)

  # create the file F1 and dir D1 which the tests regard as pre-existing
  paths = incoming_paths(wc_dir, wc_dir)  # second arg is bogus but unimportant
  F1 = paths['F1']  # existing file to copy from
  main.file_write(F1, "This is initially file F1.\n")
  main.run_svn(None, 'add', F1)
  D1 = paths['D1']  # existing dir to copy from
  main.run_svn(None, 'mkdir', D1)

  # create the initial parent dirs, and each file or dir unless to-be-added
  for init_mods, action_mods in scenarios:
    path = "_".join(action_mods)
    P = os.path.join(br_dir, path)  # parent of items to be tested
    main.run_svn(None, 'mkdir', '--parents', P)
    for modaction in init_mods:
      modify(modaction, incoming_paths(wc_dir, P))
  run_and_verify_svn(None, AnyOutput, [],
                     'commit', '-m', 'Initial set-up.', wc_dir)
  # Capture the revision number
  init_rev = 2  ### hard-coded

  # modify all files and dirs in their various ways
  for _path, action_mods in scenarios:
    path = "_".join(action_mods)
    P = os.path.join(br_dir, path)  # parent
    for modaction in action_mods:
      modify(modaction, incoming_paths(wc_dir, P))

  # commit all the modifications
  run_and_verify_svn(None, AnyOutput, [],
                     'commit', '-m', 'Action.', wc_dir)
  # Capture the revision number
  changed_rev = 3  ### hard-coded

  return (init_rev, changed_rev)
def set_up_repos(wc_dir, br_dir, scenarios):

    if not os.path.exists(br_dir):
        main.run_svn(None, "mkdir", "--parents", br_dir)

    # create the file F1 and dir D1 which the tests regard as pre-existing
    paths = incoming_paths(wc_dir, wc_dir)  # second arg is bogus but unimportant
    F1 = paths["F1"]  # existing file to copy from
    main.file_write(F1, "This is initially file F1.\n")
    main.run_svn(None, "add", F1)
    D1 = paths["D1"]  # existing dir to copy from
    main.run_svn(None, "mkdir", D1)

    # create the initial parent dirs, and each file or dir unless to-be-added
    for init_mods, action_mods in scenarios:
        path = "_".join(action_mods)
        P = os.path.join(br_dir, path)  # parent of items to be tested
        main.run_svn(None, "mkdir", "--parents", P)
        for modaction in init_mods:
            modify(modaction, incoming_paths(wc_dir, P))
    run_and_verify_svn(None, AnyOutput, [], "commit", "-m", "Initial set-up.", wc_dir)
    # Capture the revision number
    init_rev = 2  ### hard-coded

    # modify all files and dirs in their various ways
    for _path, action_mods in scenarios:
        path = "_".join(action_mods)
        P = os.path.join(br_dir, path)  # parent
        for modaction in action_mods:
            modify(modaction, incoming_paths(wc_dir, P))

    # commit all the modifications
    run_and_verify_svn(None, AnyOutput, [], "commit", "-m", "Action.", wc_dir)
    # Capture the revision number
    changed_rev = 3  ### hard-coded

    return (init_rev, changed_rev)
Exemplo n.º 13
0
def deep_trees_run_tests_scheme_for_update(sbox, greater_scheme):
    """
  Runs a given list of tests for conflicts occuring at an update operation.

  This function wants to save time and perform a number of different
  test cases using just a single repository and performing just one commit
  for all test cases instead of one for each test case.

   1) Each test case is initialized in a separate subdir. Each subdir
      again contains one set of "deep_trees", being separate container
      dirs for different depths of trees (F, D, DF, DD, DDF, DDD).

   2) A commit is performed across all test cases and depths.
      (our initial state, -r2)

   3) In each test case subdir (e.g. "local_tree_del_incoming_leaf_edit"),
      its *incoming* action is performed (e.g. "deep_trees_leaf_edit"), in
      each of the different depth trees (F, D, DF, ... DDD).

   4) A commit is performed across all test cases and depths:
      our "incoming" state is "stored away in the repository for now",
      -r3.

   5) All test case dirs and contained deep_trees are time-warped
      (updated) back to -r2, the initial state containing deep_trees.

   6) In each test case subdir (e.g. "local_tree_del_incoming_leaf_edit"),
      its *local* action is performed (e.g. "deep_trees_leaf_del"), in
      each of the different depth trees (F, D, DF, ... DDD).

   7) An update to -r3 is performed across all test cases and depths.
      This causes tree-conflicts between the "local" state in the working
      copy and the "incoming" state from the repository, -r3.

   8) A commit is performed in each separate container, to verify
      that each tree-conflict indeed blocks a commit.

  The sbox parameter is just the sbox passed to a test function. No need
  to call sbox.build(), since it is called (once) within this function.

  The "table" greater_scheme models all of the different test cases
  that should be run using a single repository.

  greater_scheme is a list of DeepTreesTestCase items, which define complete
  test setups, so that they can be performed as described above.
  """

    j = os.path.join

    if not sbox.is_built():
        sbox.build()
    wc_dir = sbox.wc_dir

    # 1) create directories

    for test_case in greater_scheme:
        try:
            add_deep_trees(sbox, test_case.name)
        except:
            logger.warn(
                "ERROR IN: Tests scheme for update: " +
                "while setting up deep trees in '%s'", test_case.name)
            raise

    # 2) commit initial state

    main.run_svn(None, 'commit', '-m', 'initial state', wc_dir)

    # 3) apply incoming changes

    for test_case in greater_scheme:
        try:
            test_case.incoming_action(j(sbox.wc_dir, test_case.name))
        except:
            logger.warn(
                "ERROR IN: Tests scheme for update: " +
                "while performing incoming action in '%s'", test_case.name)
            raise

    # 4) commit incoming changes

    main.run_svn(None, 'commit', '-m', 'incoming changes', wc_dir)

    # 5) time-warp back to -r2

    main.run_svn(None, 'update', '-r2', wc_dir)

    # 6) apply local changes

    for test_case in greater_scheme:
        try:
            test_case.local_action(j(wc_dir, test_case.name))
        except:
            logger.warn(
                "ERROR IN: Tests scheme for update: " +
                "while performing local action in '%s'", test_case.name)
            raise

    # 7) update to -r3, conflicting with incoming changes.
    #    A lot of different things are expected.
    #    Do separate update operations for each test case.

    for test_case in greater_scheme:
        try:
            base = j(wc_dir, test_case.name)

            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.copy()
                x_status.wc_dir = base

            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)
            if x_status:
                run_and_verify_unquiet_status(base, x_status)

            x_info = test_case.expected_info or {}
            for path in x_info:
                run_and_verify_info([x_info[path]], j(base, path))

        except:
            logger.warn(
                "ERROR IN: Tests scheme for update: " +
                "while verifying in '%s'", test_case.name)
            raise

    # 8) Verify that commit fails.

    for test_case in greater_scheme:
        try:
            base = j(wc_dir, test_case.name)

            x_status = test_case.expected_status
            if x_status != None:
                x_status.copy()
                x_status.wc_dir = base

            run_and_verify_commit(base, None, x_status,
                                  test_case.commit_block_string)
        except:
            logger.warn(
                "ERROR IN: Tests scheme for update: " +
                "while checking commit-blocking in '%s'", test_case.name)
            raise
Exemplo n.º 14
0
def set_up_dir_replace(sbox):
    """Set up the working copy for directory replace tests, creating
  directory 'A/B/F/foo' with files 'new file' and 'new file2' within
  it (r2), and merging 'foo' onto 'C' (r3), then deleting 'A/B/F/foo'
  (r4)."""

    sbox.build()
    wc_dir = sbox.wc_dir

    C_path = sbox.ospath('A/C')
    F_path = sbox.ospath('A/B/F')
    F_url = sbox.repo_url + '/A/B/F'

    foo_path = os.path.join(F_path, 'foo')
    new_file = os.path.join(foo_path, "new file")
    new_file2 = os.path.join(foo_path, "new file 2")

    # Make directory foo in F, and add some files within it.
    actions.run_and_verify_svn(None, [], 'mkdir', foo_path)
    main.file_append(new_file, "Initial text in new file.\n")
    main.file_append(new_file2, "Initial text in new file 2.\n")
    main.run_svn(None, "add", new_file)
    main.run_svn(None, "add", new_file2)

    # Commit all the new content, creating r2.
    expected_output = wc.State(
        wc_dir, {
            'A/B/F/foo': Item(verb='Adding'),
            'A/B/F/foo/new file': Item(verb='Adding'),
            'A/B/F/foo/new file 2': Item(verb='Adding'),
        })
    expected_status = actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/B/F/foo': Item(status='  ', wc_rev=2),
        'A/B/F/foo/new file': Item(status='  ', wc_rev=2),
        'A/B/F/foo/new file 2': Item(status='  ', wc_rev=2),
    })
    actions.run_and_verify_commit(wc_dir, expected_output, expected_status)

    # Merge foo onto C
    expected_output = wc.State(
        C_path, {
            'foo': Item(status='A '),
            'foo/new file': Item(status='A '),
            'foo/new file 2': Item(status='A '),
        })
    expected_mergeinfo_output = wc.State(C_path, {
        '': Item(status=' U'),
    })
    expected_elision_output = wc.State(C_path, {})
    expected_disk = wc.State(
        '', {
            '': Item(props={SVN_PROP_MERGEINFO: '/A/B/F:2'}),
            'foo': Item(),
            'foo/new file': Item("Initial text in new file.\n"),
            'foo/new file 2': Item("Initial text in new file 2.\n"),
        })
    expected_status = wc.State(
        C_path, {
            '': Item(status=' M', wc_rev=1),
            'foo': Item(status='A ', wc_rev='-', copied='+'),
            'foo/new file': Item(status='  ', wc_rev='-', copied='+'),
            'foo/new file 2': Item(status='  ', wc_rev='-', copied='+'),
        })
    expected_skip = wc.State(C_path, {})
    actions.run_and_verify_merge(C_path,
                                 '1',
                                 '2',
                                 F_url,
                                 None,
                                 expected_output,
                                 expected_mergeinfo_output,
                                 expected_elision_output,
                                 expected_disk,
                                 expected_status,
                                 expected_skip,
                                 check_props=True)
    # Commit merge of foo onto C, creating r3.
    expected_output = wc.State(wc_dir, {
        'A/C': Item(verb='Sending'),
        'A/C/foo': Item(verb='Adding'),
    })
    expected_status = actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/B/F/foo': Item(status='  ', wc_rev=2),
        'A/C': Item(status='  ', wc_rev=3),
        'A/B/F/foo/new file': Item(status='  ', wc_rev=2),
        'A/B/F/foo/new file 2': Item(status='  ', wc_rev=2),
        'A/C/foo': Item(status='  ', wc_rev=3),
        'A/C/foo/new file': Item(status='  ', wc_rev=3),
        'A/C/foo/new file 2': Item(status='  ', wc_rev=3),
    })
    actions.run_and_verify_commit(wc_dir, expected_output, expected_status)

    # Delete foo on F, creating r4.
    actions.run_and_verify_svn(None, [], 'rm', foo_path)
    expected_output = wc.State(wc_dir, {
        'A/B/F/foo': Item(verb='Deleting'),
    })
    expected_status = actions.get_virginal_state(wc_dir, 1)
    expected_status.add({
        'A/C': Item(status='  ', wc_rev=3),
        'A/C/foo': Item(status='  ', wc_rev=3),
        'A/C/foo/new file': Item(status='  ', wc_rev=3),
        'A/C/foo/new file 2': Item(status='  ', wc_rev=3),
    })
    actions.run_and_verify_commit(wc_dir, expected_output, expected_status)
def modify(modaction, paths):
    F1 = paths["F1"]  # existing file to copy from
    F = paths["F"]  # target file
    F2 = paths["F2"]  # non-existing file to copy/move to
    D1 = paths["D1"]  # existing dir to copy from
    D = paths["D"]  # target dir
    D2 = paths["D2"]  # non-existing dir to copy/move to

    # print "  Mod: '" + modaction + "' '" + P + "'"

    if modaction == "ft":  # file text-mod
        assert os.path.exists(F)
        main.file_append(F, "This is a text-mod of file F.\n")
    elif modaction == "fP":  # file Prop-mod
        assert os.path.exists(F)
        main.run_svn(None, "pset", "fprop1", "A prop set on file F.", F)
    elif modaction == "dP":  # dir Prop-mod
        assert os.path.exists(D)
        main.run_svn(None, "pset", "dprop1", "A prop set on dir D.", D)
    elif modaction == "fD":  # file Delete
        assert os.path.exists(F)
        main.run_svn(None, "del", F)
    elif modaction == "dD":  # dir Delete
        assert os.path.exists(D)
        main.run_svn(None, "del", D)
    elif modaction == "fA":  # file Add (new)
        assert os.path.exists(F)
        main.run_svn(None, "add", F)
        main.run_svn(None, "pset", "fprop2", "A prop of added file F.", F)
    elif modaction == "dA":  # dir Add (new)
        assert os.path.exists(D)
        main.run_svn(None, "add", D)
        main.run_svn(None, "pset", "dprop2", "A prop of added dir D.", D)
    elif modaction == "fC":  # file Copy (from F1)
        main.run_svn(None, "copy", F1, F)
    elif modaction == "dC":  # dir Copy (from D1)
        main.run_svn(None, "copy", D1, D)
    elif modaction == "fM":  # file Move (to F2)
        main.run_svn(None, "rename", F, F2)
    elif modaction == "dM":  # dir Move (to D2)
        main.run_svn(None, "rename", D, D2)
    elif modaction == "fa":  # file add (new) on disk
        assert not os.path.exists(F)
        main.file_write(F, "This is file F.\n")
    elif modaction == "da":  # dir add (new) on disk
        assert not os.path.exists(D)
        os.mkdir(D)
    elif modaction == "fd":  # file delete from disk
        assert os.path.exists(F)
        os.remove(F)
    elif modaction == "dd":  # dir delete from disk
        assert os.path.exists(D)
        os.remove(D)
    else:
        raise Exception("unknown modaction: '" + modaction + "'")
Exemplo n.º 16
0
def ensure_tree_conflict(sbox, operation,
                         incoming_scenarios, localmod_scenarios,
                         commit_local_mods):
  sbox.build()
  wc_dir = sbox.wc_dir

  def url_of(repo_relative_path):
    return sbox.repo_url + '/' + repo_relative_path

  verbose_print("")
  verbose_print("=== Starting a set of '" + operation + "' tests.")

  # Path to source branch, relative to wc_dir.
  # Source is where the "incoming" mods are made.
  source_br = "branch1"

  verbose_print("--- Creating changes in repos")
  source_wc_dir = os.path.join(wc_dir, source_br)
  source_left_rev, source_right_rev = set_up_repos(wc_dir, source_wc_dir,
                                                   incoming_scenarios)
  head_rev = source_right_rev  ### assumption

  # Local mods are the outer loop because cleaning up the WC is slow
  # ('svn revert' isn't sufficient because it leaves unversioned files)
  for _loc_init_mods, loc_action in localmod_scenarios:
    # Determine the branch (directory) in which local mods will be made.
    if operation == 'update':
      # Path to target branch (where conflicts are raised), relative to wc_dir.
      target_br = source_br
      target_start_rev = source_left_rev
    else:  # switch/merge
      # Make, and work in, a "branch2" that is a copy of "branch1".
      target_br = "branch2"
      run_and_verify_svn(None, AnyOutput, [],
                         'copy', '-r', str(source_left_rev), url_of(source_br),
                         url_of(target_br),
                         '-m', 'Create target branch.')
      head_rev += 1
      target_start_rev = head_rev

    main.run_svn(None, 'checkout', '-r', str(target_start_rev), sbox.repo_url,
                 wc_dir)

    saved_cwd = os.getcwd()
    os.chdir(wc_dir)

    for _inc_init_mods, inc_action in incoming_scenarios:
      scen_name = "_".join(inc_action)
      source_url = url_of(source_br + '/' + scen_name)
      target_path = os.path.join(target_br, scen_name)

      verbose_print("=== " + str(inc_action) + " onto " + str(loc_action))

      verbose_print("--- Making local mods")
      for modaction in loc_action:
        modify(modaction, localmod_paths(".", target_path))
      if commit_local_mods:
        run_and_verify_svn(None, AnyOutput, [],
                           'commit', target_path,
                           '-m', 'Mods in target branch.')
        head_rev += 1

      # What do we want to test for? (This selection could in future be
      # passed in to this function as a parameter.)
      test_what = [
        'commit-ood',
        'action',  # required for any of the following ones to work
        'notify',
        'commit-c',
        'status-c',
        'resolve',  # required for any of the following ones to work
        'status-nc',
        #'commit-ok',
        ]

      if 'commit-ood' in test_what:
        # For update, verify the pre-condition that WC is out of date.
        # For switch/merge, there is no such precondition.
        if operation == 'update':
          verbose_print("--- Trying to commit (expecting 'out-of-date' error)")
          run_and_verify_commit(".", None, None, "Commit failed",
                                target_path)

      if modaction.startswith('f'):
        victim = os.path.join(target_path, 'F')
      else:
        victim = os.path.join(target_path, 'D')

      # Perform the operation that tries to apply incoming changes to the WC.
      # The command is expected to do something (and give some output),
      # and it should raise a conflict but not an error.
      if 'action' in test_what:
        # Determine what notification to expect
        if 'notify' in test_what:
          expected_stdout = svntest.verify.ExpectedOutput("   C " + victim
                                                          + "\n",
                                                          match_all=False)
        else:
          expected_stdout = svntest.verify.AnyOutput
        # Do the main action
        if operation == 'update':
          verbose_print("--- Updating")
          run_and_verify_svn(None, expected_stdout, [],
                             'update', target_path)
        elif operation == 'switch':
          verbose_print("--- Switching")
          run_and_verify_svn(None, expected_stdout, [],
                             'switch', source_url, target_path)
        elif operation == 'merge':
          verbose_print("--- Merging")
          run_and_verify_svn(None, expected_stdout, [],
                             'merge', '--ignore-ancestry',
                             '-r', str(source_left_rev) + ':' + str(source_right_rev),
                             source_url, target_path)
        else:
          raise Exception("unknown operation: '" + operation + "'")

      if 'commit-c' in test_what:
        verbose_print("--- Trying to commit (expecting 'conflict' error)")
        ### run_and_verify_commit() requires an "output_tree" argument, but
        # here we get away with passing None because we know an implementation
        # detail: namely that it's not going to look at that argument if it
        # gets the stderr that we're expecting.
        run_and_verify_commit(".", None, None, ".*conflict.*", victim)

      if 'status-c' in test_what:
        verbose_print("--- Checking that 'status' reports the conflict")
        expected_stdout = svntest.verify.RegexOutput("^......C.* " +
                                                     re.escape(victim) + "$",
                                                     match_all=False)
        run_and_verify_svn(None, expected_stdout, [],
                           'status', victim)

      if 'resolve' in test_what:
        verbose_print("--- Resolving the conflict")
        # Make sure resolving the parent does nothing.
        run_and_verify_resolved([], os.path.dirname(victim))
        # The real resolved call.
        run_and_verify_resolved([victim])

      if 'status-nc' in test_what:
        verbose_print("--- Checking that 'status' does not report a conflict")
        exitcode, stdout, stderr = run_and_verify_svn(None, None, [],
                                                  'status', victim)
        for line in stdout:
          if line[6] == 'C': # and line.endswith(victim + '\n'):
            raise svntest.Failure("unexpected status C") # on path '" + victim + "'")

      if 'commit-ok' in test_what:
        verbose_print("--- Committing (should now succeed)")
        run_and_verify_svn(None, None, [],
                           'commit', '-m', '', target_path)
        target_start_rev += 1

      verbose_print("")

    os.chdir(saved_cwd)

    # Clean up the target branch and WC
    main.run_svn(None, 'revert', '-R', wc_dir)
    main.safe_rmtree(wc_dir)
    if operation != 'update':
      run_and_verify_svn(None, AnyOutput, [],
                         'delete', url_of(target_br),
                         '-m', 'Delete target branch.')
      head_rev += 1
Exemplo n.º 17
0
def replace_symlinks(sbox):
    "replace symlinks"
    sbox.build()
    wc = sbox.ospath

    # Some of these tests are implemented for git (in test script
    # t/t9100-git-svn-basic.sh) using the Perl bindings for Subversion.
    # Our issue #4091 is about 'svn update' failures in the git tests.

    sbox.simple_mkdir('A/D/G/Z')
    sbox.simple_mkdir('A/D/Gx')
    sbox.simple_mkdir('A/D/Gx/Z')
    sbox.simple_mkdir('A/D/Hx')
    sbox.simple_mkdir('A/D/Y')
    sbox.simple_mkdir('Ax')

    os.symlink('../Y', wc('A/D/H/Z'))
    os.symlink('../Y', wc('A/D/Hx/Z'))
    sbox.simple_add('A/D/H/Z', 'A/D/Hx/Z')

    for p in [
            'Ax/mu',
            'A/D/Gx/pi',
            'A/D/Hx/chi',
    ]:
        file_write(wc(p), 'This starts as a normal file.\n')
        sbox.simple_add(p)
    for p in [
            'iota.sh',
            'A/mu.sh',
            'Ax/mu.sh',
            'A/D/gamma.sh',
            'A/B/E/beta.sh',
            'A/D/G/rho.sh',
            'A/D/Gx/rho.sh',
            'A/D/H/psi.sh',
            'A/D/Hx/psi.sh',
    ]:
        file_write(wc(p), '#!/bin/sh\necho "hello, svn!"\n')
        os.chmod(wc(p), 0775)
        sbox.simple_add(p)
    sbox.simple_commit()  # r2

    # Failing git-svn test: 'new symlink is added to a file that was
    # also just made executable', i.e., in the same revision.
    sbox.simple_propset("svn:executable", "*", 'A/B/E/alpha')
    os.symlink('alpha', wc('A/B/E/sym-alpha'))
    sbox.simple_add('A/B/E/sym-alpha')

    # Add a symlink to a file made non-executable in the same revision.
    sbox.simple_propdel("svn:executable", 'A/B/E/beta.sh')
    os.symlink('beta.sh', wc('A/B/E/sym-beta.sh'))
    sbox.simple_add('A/B/E/sym-beta.sh')

    # Replace a normal {file, exec, dir} with a symlink to the same kind
    # via Subversion replacement.
    sbox.simple_rm(
        'A/D/G/pi',
        'A/D/G/rho.sh',
        #'A/D/G/Z', # Ooops, not compatible with --bin=svn1.6.
    )
    os.symlink(wc('../gamma'), wc('A/D/G/pi'))
    os.symlink(wc('../gamma.sh'), wc('A/D/G/rho.sh'))
    #os.symlink(wc('../Y'), wc('A/D/G/Z'))
    sbox.simple_add(
        'A/D/G/pi',
        'A/D/G/rho.sh',
        #'A/D/G/Z',
    )

    # Replace a symlink to {file, exec, dir} with a normal item of the
    # same kind via Subversion replacement.
    sbox.simple_rm(
        'A/D/H/chi',
        'A/D/H/psi.sh',
        #'A/D/H/Z',
    )
    os.symlink(wc('../gamma'), wc('A/D/H/chi'))
    os.symlink(wc('../gamma.sh'), wc('A/D/H/psi.sh'))
    #os.symlink(wc('../Y'), wc('A/D/H/Z'))
    sbox.simple_add(
        'A/D/H/chi',
        'A/D/H/psi.sh',
        #'A/D/H/Z',
    )

    # Replace a normal {file, exec} with a symlink to {exec, file} via
    # Subversion replacement.
    sbox.simple_rm('A/mu', 'A/mu.sh')
    os.symlink('../iota2', wc('A/mu'))
    os.symlink('../iota', wc('A/mu.sh'))
    sbox.simple_add('A/mu', 'A/mu.sh')

    # Ditto, without the Subversion replacement.  Failing git-svn test
    # 'executable file becomes a symlink to bar/zzz (file)'.
    os.remove(wc('Ax/mu'))
    os.remove(wc('Ax/mu.sh'))
    os.symlink('../iota2', wc('Ax/mu'))
    os.symlink('../iota', wc('Ax/mu.sh'))
    sbox.simple_propset('svn:special', '*', 'Ax/mu', 'Ax/mu.sh')
    sbox.simple_propdel('svn:executable', 'Ax/mu.sh')

    ### TODO Replace a normal {file, exec, dir, dir} with a symlink to
    ### {dir, dir, file, exec}.  And the same symlink-to-normal.

    ### Commit fails as of r1226697 with either "svn: E145001: Entry
    ### '.../A/D/Gx/Z' has unexpectedly changed special status" or "svn:
    ### E155010: The node '.../Ax/mu' was not found".
    sbox.simple_commit()  # r3

    # Try updating from HEAD-1 to HEAD.
    run_svn(None, 'up', '-r2', sbox.wc_dir)
    sbox.simple_update()
Exemplo n.º 18
0
def replace_symlinks(sbox):
    "replace symlinks"
    sbox.build()
    wc = sbox.ospath

    # Some of these tests are implemented for git (in test script
    # t/t9100-git-svn-basic.sh) using the Perl bindings for Subversion.
    # Our issue #4091 is about 'svn update' failures in the git tests.

    sbox.simple_mkdir('A/D/G/Z')
    sbox.simple_mkdir('A/D/Gx')
    sbox.simple_mkdir('A/D/Gx/Z')
    sbox.simple_mkdir('A/D/Hx')
    sbox.simple_mkdir('A/D/Y')
    sbox.simple_mkdir('Ax')

    sbox.simple_add_symlink('../Y', 'A/D/H/Z')
    sbox.simple_add_symlink('../Y', 'A/D/Hx/Z')

    for p in [
            'Ax/mu',
            'A/D/Gx/pi',
            'A/D/Hx/chi',
    ]:
        file_write(wc(p), 'This starts as a normal file.\n')
        sbox.simple_add(p)
    for p in [
            'iota.sh',
            'A/mu.sh',
            'Ax/mu.sh',
            'A/D/gamma.sh',
            'A/B/E/beta.sh',
            'A/D/G/rho.sh',
            'A/D/Gx/rho.sh',
            'A/D/H/psi.sh',
            'A/D/Hx/psi.sh',
    ]:
        file_write(wc(p), '#!/bin/sh\necho "hello, svn!"\n')
        os.chmod(wc(p), svntest.main.S_ALL_RW | stat.S_IXUSR)
        sbox.simple_add(p)
        if not svntest.main.is_posix_os():
            sbox.simple_propset('svn:executable', 'X', p)
    sbox.simple_commit()  # r2
    sbox.simple_update()
    expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 2)
    expected_status.add({
        'A/D/Y': Item(status='  ', wc_rev=2),
        'A/D/G/Z': Item(status='  ', wc_rev=2),
        'A/D/G/rho.sh': Item(status='  ', wc_rev=2),
        'A/D/Hx': Item(status='  ', wc_rev=2),
        'A/D/Hx/Z': Item(status='  ', wc_rev=2),
        'A/D/Hx/chi': Item(status='  ', wc_rev=2),
        'A/D/Hx/psi.sh': Item(status='  ', wc_rev=2),
        'A/D/H/psi.sh': Item(status='  ', wc_rev=2),
        'A/D/H/Z': Item(status='  ', wc_rev=2),
        'A/D/Gx': Item(status='  ', wc_rev=2),
        'A/D/Gx/Z': Item(status='  ', wc_rev=2),
        'A/D/Gx/pi': Item(status='  ', wc_rev=2),
        'A/D/Gx/rho.sh': Item(status='  ', wc_rev=2),
        'A/D/gamma.sh': Item(status='  ', wc_rev=2),
        'A/B/E/beta.sh': Item(status='  ', wc_rev=2),
        'Ax': Item(status='  ', wc_rev=2),
        'Ax/mu': Item(status='  ', wc_rev=2),
        'Ax/mu.sh': Item(status='  ', wc_rev=2),
        'A/mu.sh': Item(status='  ', wc_rev=2),
        'iota.sh': Item(status='  ', wc_rev=2),
    })
    expected_status_r2 = copy.deepcopy(expected_status)
    svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r2)

    # Failing git-svn test: 'new symlink is added to a file that was
    # also just made executable', i.e., in the same revision.
    sbox.simple_propset("svn:executable", "X", 'A/B/E/alpha')
    sbox.simple_add_symlink('alpha', 'A/B/E/sym-alpha')

    # Add a symlink to a file made non-executable in the same revision.
    sbox.simple_propdel("svn:executable", 'A/B/E/beta.sh')
    sbox.simple_add_symlink('beta.sh', 'A/B/E/sym-beta.sh')

    # Replace a normal {file, exec, dir} with a symlink to the same kind
    # via Subversion replacement.
    sbox.simple_rm(
        'A/D/G/pi',
        'A/D/G/rho.sh',
        #'A/D/G/Z', # Ooops, not compatible with --bin=svn1.6.
    )
    sbox.simple_add_symlink('../gamma', 'A/D/G/pi')
    sbox.simple_add_symlink('../gamma.sh', 'A/D/G/rho.sh')
    #sbox.simple_add_symlink('../Y', 'A/D/G/Z')

    # Replace a symlink to {file, exec, dir} with a normal item of the
    # same kind via Subversion replacement.
    sbox.simple_rm(
        'A/D/H/chi',
        'A/D/H/psi.sh',
        #'A/D/H/Z',
    )
    sbox.simple_add_symlink('../gamma', 'A/D/H/chi')
    sbox.simple_add_symlink('../gamma.sh', 'A/D/H/psi.sh')
    #sbox.simple_add_symlink('../Y', 'A/D/H/Z')

    # Replace a normal {file, exec} with a symlink to {exec, file} via
    # Subversion replacement.
    sbox.simple_rm('A/mu', 'A/mu.sh')
    sbox.simple_add_symlink('../iota2', 'A/mu')
    sbox.simple_add_symlink('../iota', 'A/mu.sh')

    # Ditto, without the Subversion replacement.  Failing git-svn test
    # 'executable file becomes a symlink to bar/zzz (file)'.
    if svntest.main.is_posix_os():
        os.remove(wc('Ax/mu'))
        os.remove(wc('Ax/mu.sh'))
        os.symlink('../iota2', wc('Ax/mu'))
        os.symlink('../iota', wc('Ax/mu.sh'))
    else:
        # At least modify the file a bit

        # ### Somehow this breaks the test when using multiline data?
        # ### Is that intended behavior?

        file_write(sbox.ospath('Ax/mu'), 'Link to iota2')
        file_write(sbox.ospath('Ax/mu.sh'), 'Link to iota')

    sbox.simple_propset('svn:special', 'X', 'Ax/mu', 'Ax/mu.sh')
    sbox.simple_propdel('svn:executable', 'Ax/mu.sh')

    ### TODO Replace a normal {file, exec, dir, dir} with a symlink to
    ### {dir, dir, file, exec}.  And the same symlink-to-normal.

    expected_status.tweak('A/D/G/pi',
                          'A/D/G/rho.sh',
                          'A/D/H/psi.sh',
                          'A/D/H/chi',
                          'A/mu',
                          'A/mu.sh',
                          status='RM')
    expected_status.tweak('A/B/E/beta.sh', 'A/B/E/alpha', status=' M')
    expected_status.tweak('Ax/mu', 'Ax/mu.sh', status='MM')
    expected_status.add({
        'A/B/E/sym-alpha': Item(status='A ', wc_rev=0),
        'A/B/E/sym-beta.sh': Item(status='A ', wc_rev=0),
    })
    svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)

    sbox.simple_commit()  # r3
    sbox.simple_update()

    expected_status.tweak(status='  ', wc_rev=3)
    expected_status_r3 = expected_status
    svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r3)

    # Try updating from HEAD-1 to HEAD.  This is currently XFAIL as the
    # update to HEAD-1 produces a tree conflict.
    run_svn(None, 'up', '-r2', sbox.wc_dir)
    svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r2)
    sbox.simple_update()
    svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r3)
Exemplo n.º 19
0
def deep_trees_run_tests_scheme_for_merge(sbox, greater_scheme,
                                          do_commit_local_changes,
                                          do_commit_conflicts=True,
                                          ignore_ancestry=False):
  """
  Runs a given list of tests for conflicts occuring at a merge operation.

  This function wants to save time and perform a number of different
  test cases using just a single repository and performing just one commit
  for all test cases instead of one for each test case.

   1) Each test case is initialized in a separate subdir. Each subdir
      initially contains another subdir, called "incoming", which
      contains a set of deep_trees.

   2) A commit is performed across all test cases and depths.
      (a pre-initial state)

   3) In each test case subdir, the "incoming" subdir is copied to "local",
      via the `svn copy' command. Each test case's subdir now has two sub-
      dirs: "local" and "incoming", initial states for the merge operation.

   4) An update is performed across all test cases and depths, so that the
      copies made in 3) are pulled into the wc.

   5) In each test case's "incoming" subdir, the incoming action is
      performed.

   6) A commit is performed across all test cases and depths, to commit
      the incoming changes.
      If do_commit_local_changes is True, this becomes step 7 (swap steps).

   7) In each test case's "local" subdir, the local_action is performed.
      If do_commit_local_changes is True, this becomes step 6 (swap steps).
      Then, in effect, the local changes are committed as well.

   8) In each test case subdir, the "incoming" subdir is merged into the
      "local" subdir.  If ignore_ancestry is True, then the merge is done
      with the --ignore-ancestry option, so mergeinfo is neither considered
      nor recorded.  This causes conflicts between the "local" state in the
      working copy and the "incoming" state from the incoming subdir.

   9) If do_commit_conflicts is True, then a commit is performed in each
      separate container, to verify that each tree-conflict indeed blocks
      a commit.

  The sbox parameter is just the sbox passed to a test function. No need
  to call sbox.build(), since it is called (once) within this function.

  The "table" greater_scheme models all of the different test cases
  that should be run using a single repository.

  greater_scheme is a list of DeepTreesTestCase items, which define complete
  test setups, so that they can be performed as described above.
  """

  j = os.path.join

  if not sbox.is_built():
    sbox.build()
  wc_dir = sbox.wc_dir

  # 1) Create directories.
  for test_case in greater_scheme:
    try:
      base = j(sbox.wc_dir, test_case.name)
      os.makedirs(base)
      make_deep_trees(j(base, "incoming"))
      main.run_svn(None, 'add', base)
    except:
      logger.warn("ERROR IN: Tests scheme for merge: "
          + "while setting up deep trees in '%s'", test_case.name)
      raise


  # 2) Commit pre-initial state (-r2).

  main.run_svn(None, 'commit', '-m', 'pre-initial state', wc_dir)


  # 3) Copy "incoming" to "local".

  for test_case in greater_scheme:
    try:
      base_url = sbox.repo_url + "/" + test_case.name
      incoming_url = base_url + "/incoming"
      local_url = base_url + "/local"
      main.run_svn(None, 'cp', incoming_url, local_url, '-m',
                   'copy incoming to local')
    except:
      logger.warn("ERROR IN: Tests scheme for merge: "
          + "while copying deep trees in '%s'", test_case.name)
      raise

  # 4) Update to load all of the "/local" subdirs into the working copies.

  try:
    main.run_svn(None, 'up', sbox.wc_dir)
  except:
    logger.warn("ERROR IN: Tests scheme for merge: "
          + "while updating local subdirs")
    raise


  # 5) Perform incoming actions

  for test_case in greater_scheme:
    try:
      test_case.incoming_action(j(sbox.wc_dir, test_case.name, "incoming"))
    except:
      logger.warn("ERROR IN: Tests scheme for merge: "
          + "while performing incoming action in '%s'", test_case.name)
      raise


  # 6) or 7) Commit all incoming actions

  if not do_commit_local_changes:
    try:
      main.run_svn(None, 'ci', '-m', 'Committing incoming actions',
                   sbox.wc_dir)
    except:
      logger.warn("ERROR IN: Tests scheme for merge: "
          + "while committing incoming actions")
      raise


  # 7) or 6) Perform all local actions.

  for test_case in greater_scheme:
    try:
      test_case.local_action(j(sbox.wc_dir, test_case.name, "local"))
    except:
      logger.warn("ERROR IN: Tests scheme for merge: "
          + "while performing local action in '%s'", test_case.name)
      raise


  # 6) or 7) Commit all incoming actions

  if do_commit_local_changes:
    try:
      main.run_svn(None, 'ci', '-m', 'Committing incoming and local actions',
                   sbox.wc_dir)
    except:
      logger.warn("ERROR IN: Tests scheme for merge: "
          + "while committing incoming and local actions")
      raise


  # 8) Merge all "incoming" subdirs to their respective "local" subdirs.
  #    This creates conflicts between the local changes in the "local" wc
  #    subdirs and the incoming states committed in the "incoming" subdirs.

  for test_case in greater_scheme:
    try:
      local = j(sbox.wc_dir, test_case.name, "local")
      incoming = sbox.repo_url + "/" + test_case.name + "/incoming"

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

      x_disk = test_case.expected_disk

      x_status = test_case.expected_status
      if x_status != None:
        x_status.copy()
        x_status.wc_dir = local

      x_skip = test_case.expected_skip
      if x_skip != None:
        x_skip.copy()
        x_skip.wc_dir = local

      varargs = (local,'--allow-mixed-revisions',)
      if ignore_ancestry:
        varargs = varargs + ('--ignore-ancestry',)

      run_and_verify_merge(local, '0', 'HEAD', incoming, None,
                           x_out, None, None, x_disk, None, x_skip,
                           test_case.error_re_string,
                           None, None, None, None,
                           False, False, *varargs)
      run_and_verify_unquiet_status(local, x_status)
    except:
      logger.warn("ERROR IN: Tests scheme for merge: "
          + "while verifying in '%s'", test_case.name)
      raise


  # 9) Verify that commit fails.

  if do_commit_conflicts:
    for test_case in greater_scheme:
      try:
        local = j(wc_dir, test_case.name, 'local')

        x_status = test_case.expected_status
        if x_status != None:
          x_status.copy()
          x_status.wc_dir = local

        run_and_verify_commit(local, None, x_status,
                              test_case.commit_block_string,
                              local)
      except:
        logger.warn("ERROR IN: Tests scheme for merge: "
            + "while checking commit-blocking in '%s'", test_case.name)
        raise
Exemplo n.º 20
0
def deep_trees_run_tests_scheme_for_merge(sbox,
                                          greater_scheme,
                                          do_commit_local_changes,
                                          do_commit_conflicts=True,
                                          ignore_ancestry=False):
    """
  Runs a given list of tests for conflicts occuring at a merge operation.

  This function wants to save time and perform a number of different
  test cases using just a single repository and performing just one commit
  for all test cases instead of one for each test case.

   1) Each test case is initialized in a separate subdir. Each subdir
      initially contains another subdir, called "incoming", which
      contains a set of deep_trees.

   2) A commit is performed across all test cases and depths.
      (a pre-initial state)

   3) In each test case subdir, the "incoming" subdir is copied to "local",
      via the `svn copy' command. Each test case's subdir now has two sub-
      dirs: "local" and "incoming", initial states for the merge operation.

   4) An update is performed across all test cases and depths, so that the
      copies made in 3) are pulled into the wc.

   5) In each test case's "incoming" subdir, the incoming action is
      performed.

   6) A commit is performed across all test cases and depths, to commit
      the incoming changes.
      If do_commit_local_changes is True, this becomes step 7 (swap steps).

   7) In each test case's "local" subdir, the local_action is performed.
      If do_commit_local_changes is True, this becomes step 6 (swap steps).
      Then, in effect, the local changes are committed as well.

   8) In each test case subdir, the "incoming" subdir is merged into the
      "local" subdir.  If ignore_ancestry is True, then the merge is done
      with the --ignore-ancestry option, so mergeinfo is neither considered
      nor recorded.  This causes conflicts between the "local" state in the
      working copy and the "incoming" state from the incoming subdir.

   9) If do_commit_conflicts is True, then a commit is performed in each
      separate container, to verify that each tree-conflict indeed blocks
      a commit.

  The sbox parameter is just the sbox passed to a test function. No need
  to call sbox.build(), since it is called (once) within this function.

  The "table" greater_scheme models all of the different test cases
  that should be run using a single repository.

  greater_scheme is a list of DeepTreesTestCase items, which define complete
  test setups, so that they can be performed as described above.
  """

    j = os.path.join

    if not sbox.is_built():
        sbox.build()
    wc_dir = sbox.wc_dir

    # 1) Create directories.
    for test_case in greater_scheme:
        try:
            base = j(sbox.wc_dir, test_case.name)
            os.makedirs(base)
            make_deep_trees(j(base, "incoming"))
            main.run_svn(None, 'add', base)
        except:
            logger.warn(
                "ERROR IN: Tests scheme for merge: " +
                "while setting up deep trees in '%s'", test_case.name)
            raise

    # 2) Commit pre-initial state (-r2).

    main.run_svn(None, 'commit', '-m', 'pre-initial state', wc_dir)

    # 3) Copy "incoming" to "local".

    for test_case in greater_scheme:
        try:
            base_url = sbox.repo_url + "/" + test_case.name
            incoming_url = base_url + "/incoming"
            local_url = base_url + "/local"
            main.run_svn(None, 'cp', incoming_url, local_url, '-m',
                         'copy incoming to local')
        except:
            logger.warn(
                "ERROR IN: Tests scheme for merge: " +
                "while copying deep trees in '%s'", test_case.name)
            raise

    # 4) Update to load all of the "/local" subdirs into the working copies.

    try:
        main.run_svn(None, 'up', sbox.wc_dir)
    except:
        logger.warn("ERROR IN: Tests scheme for merge: " +
                    "while updating local subdirs")
        raise

    # 5) Perform incoming actions

    for test_case in greater_scheme:
        try:
            test_case.incoming_action(
                j(sbox.wc_dir, test_case.name, "incoming"))
        except:
            logger.warn(
                "ERROR IN: Tests scheme for merge: " +
                "while performing incoming action in '%s'", test_case.name)
            raise

    # 6) or 7) Commit all incoming actions

    if not do_commit_local_changes:
        try:
            main.run_svn(None, 'ci', '-m', 'Committing incoming actions',
                         sbox.wc_dir)
        except:
            logger.warn("ERROR IN: Tests scheme for merge: " +
                        "while committing incoming actions")
            raise

    # 7) or 6) Perform all local actions.

    for test_case in greater_scheme:
        try:
            test_case.local_action(j(sbox.wc_dir, test_case.name, "local"))
        except:
            logger.warn(
                "ERROR IN: Tests scheme for merge: " +
                "while performing local action in '%s'", test_case.name)
            raise

    # 6) or 7) Commit all incoming actions

    if do_commit_local_changes:
        try:
            main.run_svn(None, 'ci', '-m',
                         'Committing incoming and local actions', sbox.wc_dir)
        except:
            logger.warn("ERROR IN: Tests scheme for merge: " +
                        "while committing incoming and local actions")
            raise

    # 8) Merge all "incoming" subdirs to their respective "local" subdirs.
    #    This creates conflicts between the local changes in the "local" wc
    #    subdirs and the incoming states committed in the "incoming" subdirs.

    for test_case in greater_scheme:
        try:
            local = j(sbox.wc_dir, test_case.name, "local")
            incoming = sbox.repo_url + "/" + test_case.name + "/incoming"

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

            x_disk = test_case.expected_disk

            x_status = test_case.expected_status
            if x_status != None:
                x_status.copy()
                x_status.wc_dir = local

            x_skip = test_case.expected_skip
            if x_skip != None:
                x_skip.copy()
                x_skip.wc_dir = local

            varargs = (
                local,
                '--allow-mixed-revisions',
            )
            if ignore_ancestry:
                varargs = varargs + ('--ignore-ancestry', )

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

            run_and_verify_merge(local, '0', 'HEAD', incoming, None, x_out,
                                 None, None, x_disk, None, x_skip,
                                 expected_stderr, False, False, *varargs)
            run_and_verify_unquiet_status(local, x_status)
        except:
            logger.warn(
                "ERROR IN: Tests scheme for merge: " +
                "while verifying in '%s'", test_case.name)
            raise

    # 9) Verify that commit fails.

    if do_commit_conflicts:
        for test_case in greater_scheme:
            try:
                local = j(wc_dir, test_case.name, 'local')

                x_status = test_case.expected_status
                if x_status != None:
                    x_status.copy()
                    x_status.wc_dir = local

                run_and_verify_commit(local, None, x_status,
                                      test_case.commit_block_string)
            except:
                logger.warn(
                    "ERROR IN: Tests scheme for merge: " +
                    "while checking commit-blocking in '%s'", test_case.name)
                raise
Exemplo n.º 21
0
def deep_trees_run_tests_scheme_for_update(sbox, greater_scheme):
  """
  Runs a given list of tests for conflicts occuring at an update operation.

  This function wants to save time and perform a number of different
  test cases using just a single repository and performing just one commit
  for all test cases instead of one for each test case.

   1) Each test case is initialized in a separate subdir. Each subdir
      again contains one set of "deep_trees", being separate container
      dirs for different depths of trees (F, D, DF, DD, DDF, DDD).

   2) A commit is performed across all test cases and depths.
      (our initial state, -r2)

   3) In each test case subdir (e.g. "local_tree_del_incoming_leaf_edit"),
      its *incoming* action is performed (e.g. "deep_trees_leaf_edit"), in
      each of the different depth trees (F, D, DF, ... DDD).

   4) A commit is performed across all test cases and depths:
      our "incoming" state is "stored away in the repository for now",
      -r3.

   5) All test case dirs and contained deep_trees are time-warped
      (updated) back to -r2, the initial state containing deep_trees.

   6) In each test case subdir (e.g. "local_tree_del_incoming_leaf_edit"),
      its *local* action is performed (e.g. "deep_trees_leaf_del"), in
      each of the different depth trees (F, D, DF, ... DDD).

   7) An update to -r3 is performed across all test cases and depths.
      This causes tree-conflicts between the "local" state in the working
      copy and the "incoming" state from the repository, -r3.

   8) A commit is performed in each separate container, to verify
      that each tree-conflict indeed blocks a commit.

  The sbox parameter is just the sbox passed to a test function. No need
  to call sbox.build(), since it is called (once) within this function.

  The "table" greater_scheme models all of the different test cases
  that should be run using a single repository.

  greater_scheme is a list of DeepTreesTestCase items, which define complete
  test setups, so that they can be performed as described above.
  """

  j = os.path.join

  if not sbox.is_built():
    sbox.build()
  wc_dir = sbox.wc_dir


  # 1) create directories

  for test_case in greater_scheme:
    try:
      add_deep_trees(sbox, test_case.name)
    except:
      logger.warn("ERROR IN: Tests scheme for update: "
          + "while setting up deep trees in '%s'", test_case.name)
      raise


  # 2) commit initial state

  main.run_svn(None, 'commit', '-m', 'initial state', wc_dir)


  # 3) apply incoming changes

  for test_case in greater_scheme:
    try:
      test_case.incoming_action(j(sbox.wc_dir, test_case.name))
    except:
      logger.warn("ERROR IN: Tests scheme for update: "
          + "while performing incoming action in '%s'", test_case.name)
      raise


  # 4) commit incoming changes

  main.run_svn(None, 'commit', '-m', 'incoming changes', wc_dir)


  # 5) time-warp back to -r2

  main.run_svn(None, 'update', '-r2', wc_dir)


  # 6) apply local changes

  for test_case in greater_scheme:
    try:
      test_case.local_action(j(wc_dir, test_case.name))
    except:
      logger.warn("ERROR IN: Tests scheme for update: "
          + "while performing local action in '%s'", test_case.name)
      raise


  # 7) update to -r3, conflicting with incoming changes.
  #    A lot of different things are expected.
  #    Do separate update operations for each test case.

  for test_case in greater_scheme:
    try:
      base = j(wc_dir, test_case.name)

      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.copy()
        x_status.wc_dir = base

      run_and_verify_update(base, x_out, x_disk, None,
                            error_re_string = test_case.error_re_string)
      if x_status:
        run_and_verify_unquiet_status(base, x_status)

      x_info = test_case.expected_info or {}
      for path in x_info:
        run_and_verify_info([x_info[path]], j(base, path))

    except:
      logger.warn("ERROR IN: Tests scheme for update: "
          + "while verifying in '%s'", test_case.name)
      raise


  # 8) Verify that commit fails.

  for test_case in greater_scheme:
    try:
      base = j(wc_dir, test_case.name)

      x_status = test_case.expected_status
      if x_status != None:
        x_status.copy()
        x_status.wc_dir = base

      run_and_verify_commit(base, None, x_status,
                            test_case.commit_block_string,
                            base)
    except:
      logger.warn("ERROR IN: Tests scheme for update: "
          + "while checking commit-blocking in '%s'", test_case.name)
      raise
def ensure_tree_conflict(sbox, operation, incoming_scenarios, localmod_scenarios, commit_local_mods):
    sbox.build()
    wc_dir = sbox.wc_dir

    def url_of(repo_relative_path):
        return sbox.repo_url + "/" + repo_relative_path

    verbose_print("")
    verbose_print("=== Starting a set of '" + operation + "' tests.")

    # Path to source branch, relative to wc_dir.
    # Source is where the "incoming" mods are made.
    source_br = "branch1"

    verbose_print("--- Creating changes in repos")
    source_wc_dir = os.path.join(wc_dir, source_br)
    source_left_rev, source_right_rev = set_up_repos(wc_dir, source_wc_dir, incoming_scenarios)
    head_rev = source_right_rev  ### assumption

    # Local mods are the outer loop because cleaning up the WC is slow
    # ('svn revert' isn't sufficient because it leaves unversioned files)
    for _loc_init_mods, loc_action in localmod_scenarios:
        # Determine the branch (directory) in which local mods will be made.
        if operation == "update":
            # Path to target branch (where conflicts are raised), relative to wc_dir.
            target_br = source_br
            target_start_rev = source_left_rev
        else:  # switch/merge
            # Make, and work in, a "branch2" that is a copy of "branch1".
            target_br = "branch2"
            run_and_verify_svn(
                None,
                AnyOutput,
                [],
                "copy",
                "-r",
                str(source_left_rev),
                url_of(source_br),
                url_of(target_br),
                "-m",
                "Create target branch.",
            )
            head_rev += 1
            target_start_rev = head_rev

        main.run_svn(None, "checkout", "-r", str(target_start_rev), sbox.repo_url, wc_dir)

        saved_cwd = os.getcwd()
        os.chdir(wc_dir)

        for _inc_init_mods, inc_action in incoming_scenarios:
            scen_name = "_".join(inc_action)
            source_url = url_of(source_br + "/" + scen_name)
            target_path = os.path.join(target_br, scen_name)

            verbose_print("=== " + str(inc_action) + " onto " + str(loc_action))

            verbose_print("--- Making local mods")
            for modaction in loc_action:
                modify(modaction, localmod_paths(".", target_path))
            if commit_local_mods:
                run_and_verify_svn(None, AnyOutput, [], "commit", target_path, "-m", "Mods in target branch.")
                head_rev += 1

            # What do we want to test for? (This selection could in future be
            # passed in to this function as a parameter.)
            test_what = [
                "commit-ood",
                "action",  # required for any of the following ones to work
                "notify",
                "commit-c",
                "status-c",
                "resolve",  # required for any of the following ones to work
                "status-nc",
                #'commit-ok',
            ]

            if "commit-ood" in test_what:
                # For update, verify the pre-condition that WC is out of date.
                # For switch/merge, there is no such precondition.
                if operation == "update":
                    verbose_print("--- Trying to commit (expecting 'out-of-date' error)")
                    run_and_verify_commit(".", None, None, "Commit failed", target_path)

            if modaction.startswith("f"):
                victim = os.path.join(target_path, "F")
            else:
                victim = os.path.join(target_path, "D")

            # Perform the operation that tries to apply incoming changes to the WC.
            # The command is expected to do something (and give some output),
            # and it should raise a conflict but not an error.
            if "action" in test_what:
                # Determine what notification to expect
                if "notify" in test_what:
                    expected_stdout = svntest.verify.ExpectedOutput("   C " + victim + "\n", match_all=False)
                else:
                    expected_stdout = svntest.verify.AnyOutput
                # Do the main action
                if operation == "update":
                    verbose_print("--- Updating")
                    run_and_verify_svn(None, expected_stdout, [], "update", target_path)
                elif operation == "switch":
                    verbose_print("--- Switching")
                    run_and_verify_svn(None, expected_stdout, [], "switch", source_url, target_path)
                elif operation == "merge":
                    verbose_print("--- Merging")
                    run_and_verify_svn(
                        None,
                        expected_stdout,
                        [],
                        "merge",
                        "--ignore-ancestry",
                        "-r",
                        str(source_left_rev) + ":" + str(source_right_rev),
                        source_url,
                        target_path,
                    )
                else:
                    raise Exception("unknown operation: '" + operation + "'")

            if "commit-c" in test_what:
                verbose_print("--- Trying to commit (expecting 'conflict' error)")
                ### run_and_verify_commit() requires an "output_tree" argument, but
                # here we get away with passing None because we know an implementation
                # detail: namely that it's not going to look at that argument if it
                # gets the stderr that we're expecting.
                run_and_verify_commit(".", None, None, ".*conflict.*", victim)

            if "status-c" in test_what:
                verbose_print("--- Checking that 'status' reports the conflict")
                expected_stdout = svntest.verify.RegexOutput("^......C.* " + re.escape(victim) + "$", match_all=False)
                run_and_verify_svn(None, expected_stdout, [], "status", victim)

            if "resolve" in test_what:
                verbose_print("--- Resolving the conflict")
                # Make sure resolving the parent does nothing.
                run_and_verify_resolved([], os.path.dirname(victim))
                # The real resolved call.
                run_and_verify_resolved([victim])

            if "status-nc" in test_what:
                verbose_print("--- Checking that 'status' does not report a conflict")
                exitcode, stdout, stderr = run_and_verify_svn(None, None, [], "status", victim)
                for line in stdout:
                    if line[6] == "C":  # and line.endswith(victim + '\n'):
                        raise svntest.Failure("unexpected status C")  # on path '" + victim + "'")

            if "commit-ok" in test_what:
                verbose_print("--- Committing (should now succeed)")
                run_and_verify_svn(None, None, [], "commit", "-m", "", target_path)
                target_start_rev += 1

            verbose_print("")

        os.chdir(saved_cwd)

        # Clean up the target branch and WC
        main.run_svn(None, "revert", "-R", wc_dir)
        main.safe_rmtree(wc_dir)
        if operation != "update":
            run_and_verify_svn(None, AnyOutput, [], "delete", url_of(target_br), "-m", "Delete target branch.")
            head_rev += 1
Exemplo n.º 23
0
def deep_trees_run_tests_scheme_for_switch(sbox, greater_scheme):
    """
  Runs a given list of tests for conflicts occuring at a switch operation.

  This function wants to save time and perform a number of different
  test cases using just a single repository and performing just one commit
  for all test cases instead of one for each test case.

   1) Each test case is initialized in a separate subdir. Each subdir
      again contains two subdirs: one "local" and one "incoming" for
      the switch operation. These contain a set of deep_trees each.

   2) A commit is performed across all test cases and depths.
      (our initial state, -r2)

   3) In each test case subdir's incoming subdir, the
      incoming actions are performed.

   4) A commit is performed across all test cases and depths. (-r3)

   5) In each test case subdir's local subdir, the local actions are
      performed. They remain uncommitted in the working copy.

   6) In each test case subdir's local dir, a switch is performed to its
      corresponding incoming dir.
      This causes conflicts between the "local" state in the working
      copy and the "incoming" state from the incoming subdir (still -r3).

   7) A commit is performed in each separate container, to verify
      that each tree-conflict indeed blocks a commit.

  The sbox parameter is just the sbox passed to a test function. No need
  to call sbox.build(), since it is called (once) within this function.

  The "table" greater_scheme models all of the different test cases
  that should be run using a single repository.

  greater_scheme is a list of DeepTreesTestCase items, which define complete
  test setups, so that they can be performed as described above.
  """

    j = os.path.join

    if not sbox.is_built():
        sbox.build()
    wc_dir = sbox.wc_dir

    # 1) Create directories.

    for test_case in greater_scheme:
        try:
            base = j(sbox.wc_dir, test_case.name)
            os.makedirs(base)
            make_deep_trees(j(base, "local"))
            make_deep_trees(j(base, "incoming"))
            main.run_svn(None, 'add', base)
        except:
            logger.warn(
                "ERROR IN: Tests scheme for switch: " +
                "while setting up deep trees in '%s'", test_case.name)
            raise

    # 2) Commit initial state (-r2).

    main.run_svn(None, 'commit', '-m', 'initial state', wc_dir)

    # 3) Apply incoming changes

    for test_case in greater_scheme:
        try:
            test_case.incoming_action(
                j(sbox.wc_dir, test_case.name, "incoming"))
        except:
            logger.warn(
                "ERROR IN: Tests scheme for switch: " +
                "while performing incoming action in '%s'", test_case.name)
            raise

    # 4) Commit all changes (-r3).

    main.run_svn(None, 'commit', '-m', 'incoming changes', wc_dir)

    # 5) Apply local changes in their according subdirs.

    for test_case in greater_scheme:
        try:
            test_case.local_action(j(sbox.wc_dir, test_case.name, "local"))
        except:
            logger.warn(
                "ERROR IN: Tests scheme for switch: " +
                "while performing local action in '%s'", test_case.name)
            raise

    # 6) switch the local dir to the incoming url, conflicting with incoming
    #    changes. A lot of different things are expected.
    #    Do separate switch operations for each test case.

    for test_case in greater_scheme:
        try:
            local = j(wc_dir, test_case.name, "local")
            incoming = sbox.repo_url + "/" + test_case.name + "/incoming"

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

            x_disk = test_case.expected_disk

            x_status = test_case.expected_status
            if x_status != None:
                x_status.copy()
                x_status.wc_dir = local

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

            run_and_verify_switch(local, local, incoming, x_out, x_disk, None,
                                  expected_stderr, False, '--ignore-ancestry')
            run_and_verify_unquiet_status(local, x_status)

            x_info = test_case.expected_info or {}
            for path in x_info:
                run_and_verify_info([x_info[path]], j(local, path))
        except:
            logger.warn(
                "ERROR IN: Tests scheme for switch: " +
                "while verifying in '%s'", test_case.name)
            raise

    # 7) Verify that commit fails.

    for test_case in greater_scheme:
        try:
            local = j(wc_dir, test_case.name, 'local')

            x_status = test_case.expected_status
            if x_status != None:
                x_status.copy()
                x_status.wc_dir = local

            run_and_verify_commit(local, None, x_status,
                                  test_case.commit_block_string)
        except:
            logger.warn(
                "ERROR IN: Tests scheme for switch: " +
                "while checking commit-blocking in '%s'", test_case.name)
            raise
Exemplo n.º 24
0
def modify(modaction, paths):
  F1 = paths['F1']  # existing file to copy from
  F  = paths['F']   # target file
  F2 = paths['F2']  # non-existing file to copy/move to
  D1 = paths['D1']  # existing dir to copy from
  D  = paths['D']   # target dir
  D2 = paths['D2']  # non-existing dir to copy/move to

  # print "  Mod: '" + modaction + "' '" + P + "'"

  if modaction == 'ft':    # file text-mod
    assert os.path.exists(F)
    main.file_append(F, "This is a text-mod of file F.\n")
  elif modaction == 'fP':  # file Prop-mod
    assert os.path.exists(F)
    main.run_svn(None, 'pset', 'fprop1', 'A prop set on file F.', F)
  elif modaction == 'dP':  # dir Prop-mod
    assert os.path.exists(D)
    main.run_svn(None, 'pset', 'dprop1', 'A prop set on dir D.', D)
  elif modaction == 'fD':  # file Delete
    assert os.path.exists(F)
    main.run_svn(None, 'del', F)
  elif modaction == 'dD':  # dir Delete
    assert os.path.exists(D)
    main.run_svn(None, 'del', D)
  elif modaction == 'fA':  # file Add (new)
    assert os.path.exists(F)
    main.run_svn(None, 'add', F)
    main.run_svn(None, 'pset', 'fprop2', 'A prop of added file F.', F)
  elif modaction == 'dA':  # dir Add (new)
    assert os.path.exists(D)
    main.run_svn(None, 'add', D)
    main.run_svn(None, 'pset', 'dprop2', 'A prop of added dir D.', D)
  elif modaction == 'fC':  # file Copy (from F1)
    main.run_svn(None, 'copy', F1, F)
  elif modaction == 'dC':  # dir Copy (from D1)
    main.run_svn(None, 'copy', D1, D)
  elif modaction == 'fM':  # file Move (to F2)
    main.run_svn(None, 'rename', F, F2)
  elif modaction == 'dM':  # dir Move (to D2)
    main.run_svn(None, 'rename', D, D2)
  elif modaction == 'fa':  # file add (new) on disk
    assert not os.path.exists(F)
    main.file_write(F, "This is file F.\n")
  elif modaction == 'da':  # dir add (new) on disk
    assert not os.path.exists(D)
    os.mkdir(D)
  elif modaction == 'fd':  # file delete from disk
    assert os.path.exists(F)
    os.remove(F)
  elif modaction == 'dd':  # dir delete from disk
    assert os.path.exists(D)
    os.remove(D)
  else:
    raise Exception("unknown modaction: '" + modaction + "'")
Exemplo n.º 25
0
def deep_trees_run_tests_scheme_for_switch(sbox, greater_scheme):
  """
  Runs a given list of tests for conflicts occuring at a switch operation.

  This function wants to save time and perform a number of different
  test cases using just a single repository and performing just one commit
  for all test cases instead of one for each test case.

   1) Each test case is initialized in a separate subdir. Each subdir
      again contains two subdirs: one "local" and one "incoming" for
      the switch operation. These contain a set of deep_trees each.

   2) A commit is performed across all test cases and depths.
      (our initial state, -r2)

   3) In each test case subdir's incoming subdir, the
      incoming actions are performed.

   4) A commit is performed across all test cases and depths. (-r3)

   5) In each test case subdir's local subdir, the local actions are
      performed. They remain uncommitted in the working copy.

   6) In each test case subdir's local dir, a switch is performed to its
      corresponding incoming dir.
      This causes conflicts between the "local" state in the working
      copy and the "incoming" state from the incoming subdir (still -r3).

   7) A commit is performed in each separate container, to verify
      that each tree-conflict indeed blocks a commit.

  The sbox parameter is just the sbox passed to a test function. No need
  to call sbox.build(), since it is called (once) within this function.

  The "table" greater_scheme models all of the different test cases
  that should be run using a single repository.

  greater_scheme is a list of DeepTreesTestCase items, which define complete
  test setups, so that they can be performed as described above.
  """

  j = os.path.join

  if not sbox.is_built():
    sbox.build()
  wc_dir = sbox.wc_dir


  # 1) Create directories.

  for test_case in greater_scheme:
    try:
      base = j(sbox.wc_dir, test_case.name)
      os.makedirs(base)
      make_deep_trees(j(base, "local"))
      make_deep_trees(j(base, "incoming"))
      main.run_svn(None, 'add', base)
    except:
      logger.warn("ERROR IN: Tests scheme for switch: "
          + "while setting up deep trees in '%s'", test_case.name)
      raise


  # 2) Commit initial state (-r2).

  main.run_svn(None, 'commit', '-m', 'initial state', wc_dir)


  # 3) Apply incoming changes

  for test_case in greater_scheme:
    try:
      test_case.incoming_action(j(sbox.wc_dir, test_case.name, "incoming"))
    except:
      logger.warn("ERROR IN: Tests scheme for switch: "
          + "while performing incoming action in '%s'", test_case.name)
      raise


  # 4) Commit all changes (-r3).

  main.run_svn(None, 'commit', '-m', 'incoming changes', wc_dir)


  # 5) Apply local changes in their according subdirs.

  for test_case in greater_scheme:
    try:
      test_case.local_action(j(sbox.wc_dir, test_case.name, "local"))
    except:
      logger.warn("ERROR IN: Tests scheme for switch: "
          + "while performing local action in '%s'", test_case.name)
      raise


  # 6) switch the local dir to the incoming url, conflicting with incoming
  #    changes. A lot of different things are expected.
  #    Do separate switch operations for each test case.

  for test_case in greater_scheme:
    try:
      local = j(wc_dir, test_case.name, "local")
      incoming = sbox.repo_url + "/" + test_case.name + "/incoming"

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

      x_disk = test_case.expected_disk

      x_status = test_case.expected_status
      if x_status != None:
        x_status.copy()
        x_status.wc_dir = local

      run_and_verify_switch(local, local, incoming, x_out, x_disk, None,
                            test_case.error_re_string, None, None, None,
                            None, False, '--ignore-ancestry')
      run_and_verify_unquiet_status(local, x_status)

      x_info = test_case.expected_info or {}
      for path in x_info:
        run_and_verify_info([x_info[path]], j(local, path))
    except:
      logger.warn("ERROR IN: Tests scheme for switch: "
          + "while verifying in '%s'", test_case.name)
      raise


  # 7) Verify that commit fails.

  for test_case in greater_scheme:
    try:
      local = j(wc_dir, test_case.name, 'local')

      x_status = test_case.expected_status
      if x_status != None:
        x_status.copy()
        x_status.wc_dir = local

      run_and_verify_commit(local, None, x_status,
                            test_case.commit_block_string,
                            local)
    except:
      logger.warn("ERROR IN: Tests scheme for switch: "
          + "while checking commit-blocking in '%s'", test_case.name)
      raise
Exemplo n.º 26
0
def replace_symlinks(sbox):
  "replace symlinks"
  sbox.build()
  wc = sbox.ospath

  # Some of these tests are implemented for git (in test script
  # t/t9100-git-svn-basic.sh) using the Perl bindings for Subversion.
  # Our issue #4091 is about 'svn update' failures in the git tests.

  sbox.simple_mkdir('A/D/G/Z')
  sbox.simple_mkdir('A/D/Gx')
  sbox.simple_mkdir('A/D/Gx/Z')
  sbox.simple_mkdir('A/D/Hx')
  sbox.simple_mkdir('A/D/Y')
  sbox.simple_mkdir('Ax')

  os.symlink('../Y', wc('A/D/H/Z'))
  os.symlink('../Y', wc('A/D/Hx/Z'))
  sbox.simple_add('A/D/H/Z',
                  'A/D/Hx/Z')

  for p in ['Ax/mu',
            'A/D/Gx/pi',
            'A/D/Hx/chi',
            ]:
      file_write(wc(p), 'This starts as a normal file.\n')
      sbox.simple_add(p)
  for p in ['iota.sh',
            'A/mu.sh',
            'Ax/mu.sh',
            'A/D/gamma.sh',
            'A/B/E/beta.sh',
            'A/D/G/rho.sh',
            'A/D/Gx/rho.sh',
            'A/D/H/psi.sh',
            'A/D/Hx/psi.sh',
            ]:
      file_write(wc(p), '#!/bin/sh\necho "hello, svn!"\n')
      os.chmod(wc(p), 0775)
      sbox.simple_add(p)
  sbox.simple_commit() # r2
  sbox.simple_update()
  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 2)
  expected_status.add({
    'A/D/Y'         : Item(status='  ', wc_rev=2),
    'A/D/G/Z'       : Item(status='  ', wc_rev=2),
    'A/D/G/rho.sh'  : Item(status='  ', wc_rev=2),
    'A/D/Hx'        : Item(status='  ', wc_rev=2),
    'A/D/Hx/Z'      : Item(status='  ', wc_rev=2),
    'A/D/Hx/chi'    : Item(status='  ', wc_rev=2),
    'A/D/Hx/psi.sh' : Item(status='  ', wc_rev=2),
    'A/D/H/psi.sh'  : Item(status='  ', wc_rev=2),
    'A/D/H/Z'       : Item(status='  ', wc_rev=2),
    'A/D/Gx'        : Item(status='  ', wc_rev=2),
    'A/D/Gx/Z'      : Item(status='  ', wc_rev=2),
    'A/D/Gx/pi'     : Item(status='  ', wc_rev=2),
    'A/D/Gx/rho.sh' : Item(status='  ', wc_rev=2),
    'A/D/gamma.sh'  : Item(status='  ', wc_rev=2),
    'A/B/E/beta.sh' : Item(status='  ', wc_rev=2),
    'Ax'            : Item(status='  ', wc_rev=2),
    'Ax/mu'         : Item(status='  ', wc_rev=2),
    'Ax/mu.sh'      : Item(status='  ', wc_rev=2),
    'A/mu.sh'       : Item(status='  ', wc_rev=2),
    'iota.sh'       : Item(status='  ', wc_rev=2),
    })
  expected_status_r2 = expected_status
  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r2)

  # Failing git-svn test: 'new symlink is added to a file that was
  # also just made executable', i.e., in the same revision.
  sbox.simple_propset("svn:executable", "*", 'A/B/E/alpha')
  os.symlink('alpha', wc('A/B/E/sym-alpha'))
  sbox.simple_add('A/B/E/sym-alpha')

  # Add a symlink to a file made non-executable in the same revision.
  sbox.simple_propdel("svn:executable", 'A/B/E/beta.sh')
  os.symlink('beta.sh', wc('A/B/E/sym-beta.sh'))
  sbox.simple_add('A/B/E/sym-beta.sh')

  # Replace a normal {file, exec, dir} with a symlink to the same kind
  # via Subversion replacement.
  sbox.simple_rm('A/D/G/pi',
                 'A/D/G/rho.sh',
                 #'A/D/G/Z', # Ooops, not compatible with --bin=svn1.6.
                 )
  os.symlink(wc('../gamma'), wc('A/D/G/pi'))
  os.symlink(wc('../gamma.sh'), wc('A/D/G/rho.sh'))
  #os.symlink(wc('../Y'), wc('A/D/G/Z'))
  sbox.simple_add('A/D/G/pi',
                  'A/D/G/rho.sh',
                  #'A/D/G/Z',
                  )

  # Replace a symlink to {file, exec, dir} with a normal item of the
  # same kind via Subversion replacement.
  sbox.simple_rm('A/D/H/chi',
                 'A/D/H/psi.sh',
                 #'A/D/H/Z',
                 )
  os.symlink(wc('../gamma'), wc('A/D/H/chi'))
  os.symlink(wc('../gamma.sh'), wc('A/D/H/psi.sh'))
  #os.symlink(wc('../Y'), wc('A/D/H/Z'))
  sbox.simple_add('A/D/H/chi',
                  'A/D/H/psi.sh',
                  #'A/D/H/Z',
                  )

  # Replace a normal {file, exec} with a symlink to {exec, file} via
  # Subversion replacement.
  sbox.simple_rm('A/mu',
                 'A/mu.sh')
  os.symlink('../iota2', wc('A/mu'))
  os.symlink('../iota', wc('A/mu.sh'))
  sbox.simple_add('A/mu',
                  'A/mu.sh')

  # Ditto, without the Subversion replacement.  Failing git-svn test
  # 'executable file becomes a symlink to bar/zzz (file)'.
  os.remove(wc('Ax/mu'))
  os.remove(wc('Ax/mu.sh'))
  os.symlink('../iota2', wc('Ax/mu'))
  os.symlink('../iota', wc('Ax/mu.sh'))
  sbox.simple_propset('svn:special', '*',
                      'Ax/mu',
                      'Ax/mu.sh')
  sbox.simple_propdel('svn:executable', 'Ax/mu.sh')

  ### TODO Replace a normal {file, exec, dir, dir} with a symlink to
  ### {dir, dir, file, exec}.  And the same symlink-to-normal.

  expected_status.tweak('A/D/G/pi',
                        'A/D/G/rho.sh',
                        'A/D/H/psi.sh',
                        'A/D/H/chi',
                        'A/mu',
                        'A/mu.sh',
                        status='RM')
  expected_status.tweak('A/B/E/beta.sh',
                        'A/B/E/alpha',
                        status=' M')
  expected_status.tweak('Ax/mu',
                        'Ax/mu.sh',
                        status='MM')
  expected_status.add({
      'A/B/E/sym-alpha'   : Item(status='A ', wc_rev=0),
      'A/B/E/sym-beta.sh' : Item(status='A ', wc_rev=0),
      })
  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)

  sbox.simple_commit() # r3
  sbox.simple_update()

  expected_status.tweak(status='  ', wc_rev=3)
  expected_status_r3 = expected_status
  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r3)

  # Try updating from HEAD-1 to HEAD.  This is currently XFAIL as the
  # update to HEAD-1 produces a tree conflict.
  run_svn(None, 'up', '-r2', sbox.wc_dir)
  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r2)
  sbox.simple_update()
  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r3)
Exemplo n.º 27
0
def replace_symlinks(sbox):
  "replace symlinks"
  sbox.build()
  wc = sbox.ospath

  # Some of these tests are implemented for git (in test script
  # t/t9100-git-svn-basic.sh) using the Perl bindings for Subversion.
  # Our issue #4091 is about 'svn update' failures in the git tests.

  sbox.simple_mkdir('A/D/G/Z')
  sbox.simple_mkdir('A/D/Gx')
  sbox.simple_mkdir('A/D/Gx/Z')
  sbox.simple_mkdir('A/D/Hx')
  sbox.simple_mkdir('A/D/Y')
  sbox.simple_mkdir('Ax')

  os.symlink('../Y', wc('A/D/H/Z'))
  os.symlink('../Y', wc('A/D/Hx/Z'))
  sbox.simple_add('A/D/H/Z',
                  'A/D/Hx/Z')

  for p in ['Ax/mu',
            'A/D/Gx/pi',
            'A/D/Hx/chi',
            ]:
      file_write(wc(p), 'This starts as a normal file.\n')
      sbox.simple_add(p)
  for p in ['iota.sh',
            'A/mu.sh',
            'Ax/mu.sh',
            'A/D/gamma.sh',
            'A/B/E/beta.sh',
            'A/D/G/rho.sh',
            'A/D/Gx/rho.sh',
            'A/D/H/psi.sh',
            'A/D/Hx/psi.sh',
            ]:
      file_write(wc(p), '#!/bin/sh\necho "hello, svn!"\n')
      os.chmod(wc(p), 0775)
      sbox.simple_add(p)
  sbox.simple_commit() # r2

  # Failing git-svn test: 'new symlink is added to a file that was
  # also just made executable', i.e., in the same revision.
  sbox.simple_propset("svn:executable", "*", 'A/B/E/alpha')
  os.symlink('alpha', wc('A/B/E/sym-alpha'))
  sbox.simple_add('A/B/E/sym-alpha')

  # Add a symlink to a file made non-executable in the same revision.
  sbox.simple_propdel("svn:executable", 'A/B/E/beta.sh')
  os.symlink('beta.sh', wc('A/B/E/sym-beta.sh'))
  sbox.simple_add('A/B/E/sym-beta.sh')

  # Replace a normal {file, exec, dir} with a symlink to the same kind
  # via Subversion replacement.
  sbox.simple_rm('A/D/G/pi',
                 'A/D/G/rho.sh',
                 #'A/D/G/Z', # Ooops, not compatible with --bin=svn1.6.
                 )
  os.symlink(wc('../gamma'), wc('A/D/G/pi'))
  os.symlink(wc('../gamma.sh'), wc('A/D/G/rho.sh'))
  #os.symlink(wc('../Y'), wc('A/D/G/Z'))
  sbox.simple_add('A/D/G/pi',
                  'A/D/G/rho.sh',
                  #'A/D/G/Z',
                  )

  # Replace a symlink to {file, exec, dir} with a normal item of the
  # same kind via Subversion replacement.
  sbox.simple_rm('A/D/H/chi',
                 'A/D/H/psi.sh',
                 #'A/D/H/Z',
                 )
  os.symlink(wc('../gamma'), wc('A/D/H/chi'))
  os.symlink(wc('../gamma.sh'), wc('A/D/H/psi.sh'))
  #os.symlink(wc('../Y'), wc('A/D/H/Z'))
  sbox.simple_add('A/D/H/chi',
                  'A/D/H/psi.sh',
                  #'A/D/H/Z',
                  )

  # Replace a normal {file, exec} with a symlink to {exec, file} via
  # Subversion replacement.
  sbox.simple_rm('A/mu',
                 'A/mu.sh')
  os.symlink('../iota2', wc('A/mu'))
  os.symlink('../iota', wc('A/mu.sh'))
  sbox.simple_add('A/mu',
                  'A/mu.sh')
 
  # Ditto, without the Subversion replacement.  Failing git-svn test
  # 'executable file becomes a symlink to bar/zzz (file)'.
  os.remove(wc('Ax/mu'))
  os.remove(wc('Ax/mu.sh'))
  os.symlink('../iota2', wc('Ax/mu'))
  os.symlink('../iota', wc('Ax/mu.sh'))
  sbox.simple_propset('svn:special', '*',
                      'Ax/mu',
                      'Ax/mu.sh')
  sbox.simple_propdel('svn:executable', 'Ax/mu.sh')
  
  ### TODO Replace a normal {file, exec, dir, dir} with a symlink to
  ### {dir, dir, file, exec}.  And the same symlink-to-normal.

  ### Commit fails as of r1226697 with either "svn: E145001: Entry
  ### '.../A/D/Gx/Z' has unexpectedly changed special status" or "svn:
  ### E155010: The node '.../Ax/mu' was not found".
  sbox.simple_commit() # r3

  # Try updating from HEAD-1 to HEAD.
  run_svn(None, 'up', '-r2', sbox.wc_dir)
  sbox.simple_update()
Exemplo n.º 28
0
def set_up_dir_replace(sbox):
  """Set up the working copy for directory replace tests, creating
  directory 'A/B/F/foo' with files 'new file' and 'new file2' within
  it (r2), and merging 'foo' onto 'C' (r3), then deleting 'A/B/F/foo'
  (r4)."""

  sbox.build()
  wc_dir = sbox.wc_dir

  C_path = sbox.ospath('A/C')
  F_path = sbox.ospath('A/B/F')
  F_url = sbox.repo_url + '/A/B/F'

  foo_path = os.path.join(F_path, 'foo')
  new_file = os.path.join(foo_path, "new file")
  new_file2 = os.path.join(foo_path, "new file 2")

  # Make directory foo in F, and add some files within it.
  actions.run_and_verify_svn(None, [], 'mkdir', foo_path)
  main.file_append(new_file, "Initial text in new file.\n")
  main.file_append(new_file2, "Initial text in new file 2.\n")
  main.run_svn(None, "add", new_file)
  main.run_svn(None, "add", new_file2)

  # Commit all the new content, creating r2.
  expected_output = wc.State(wc_dir, {
    'A/B/F/foo'            : Item(verb='Adding'),
    'A/B/F/foo/new file'   : Item(verb='Adding'),
    'A/B/F/foo/new file 2' : Item(verb='Adding'),
    })
  expected_status = actions.get_virginal_state(wc_dir, 1)
  expected_status.add({
    'A/B/F/foo'             : Item(status='  ', wc_rev=2),
    'A/B/F/foo/new file'    : Item(status='  ', wc_rev=2),
    'A/B/F/foo/new file 2'  : Item(status='  ', wc_rev=2),
    })
  actions.run_and_verify_commit(wc_dir, expected_output, expected_status)

  # Merge foo onto C
  expected_output = wc.State(C_path, {
    'foo' : Item(status='A '),
    'foo/new file'   : Item(status='A '),
    'foo/new file 2' : Item(status='A '),
    })
  expected_mergeinfo_output = wc.State(C_path, {
    '' : Item(status=' U'),
    })
  expected_elision_output = wc.State(C_path, {
    })
  expected_disk = wc.State('', {
    ''               : Item(props={SVN_PROP_MERGEINFO : '/A/B/F:2'}),
    'foo' : Item(),
    'foo/new file'   : Item("Initial text in new file.\n"),
    'foo/new file 2' : Item("Initial text in new file 2.\n"),
    })
  expected_status = wc.State(C_path, {
    ''    : Item(status=' M', wc_rev=1),
    'foo' : Item(status='A ', wc_rev='-', copied='+'),
    'foo/new file'   : Item(status='  ', wc_rev='-', copied='+'),
    'foo/new file 2' : Item(status='  ', wc_rev='-', copied='+'),
    })
  expected_skip = wc.State(C_path, { })
  actions.run_and_verify_merge(C_path, '1', '2', F_url, None,
                                       expected_output,
                                       expected_mergeinfo_output,
                                       expected_elision_output,
                                       expected_disk,
                                       expected_status,
                                       expected_skip,
                                       check_props=True)
  # Commit merge of foo onto C, creating r3.
  expected_output = wc.State(wc_dir, {
    'A/C'        : Item(verb='Sending'),
    'A/C/foo'    : Item(verb='Adding'),
    })
  expected_status = actions.get_virginal_state(wc_dir, 1)
  expected_status.add({
    'A/B/F/foo'  : Item(status='  ', wc_rev=2),
    'A/C'        : Item(status='  ', wc_rev=3),
    'A/B/F/foo/new file'      : Item(status='  ', wc_rev=2),
    'A/B/F/foo/new file 2'    : Item(status='  ', wc_rev=2),
    'A/C/foo'    : Item(status='  ', wc_rev=3),
    'A/C/foo/new file'      : Item(status='  ', wc_rev=3),
    'A/C/foo/new file 2'    : Item(status='  ', wc_rev=3),

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

  # Delete foo on F, creating r4.
  actions.run_and_verify_svn(None, [], 'rm', foo_path)
  expected_output = wc.State(wc_dir, {
    'A/B/F/foo'   : Item(verb='Deleting'),
    })
  expected_status = actions.get_virginal_state(wc_dir, 1)
  expected_status.add({
    'A/C'         : Item(status='  ', wc_rev=3),
    'A/C/foo'     : Item(status='  ', wc_rev=3),
    'A/C/foo/new file'      : Item(status='  ', wc_rev=3),
    'A/C/foo/new file 2'    : Item(status='  ', wc_rev=3),
    })
  actions.run_and_verify_commit(wc_dir, expected_output, expected_status)