📄 fs-test.c
字号:
SVN_ERR(svn_fs_revision_root(&revision_root, fs, after_rev, pool)); SVN_ERR(svn_test__validate_tree(revision_root, expected_entries, 20, pool)); } revisions[revision_count++] = after_rev; /* (1) E has been deleted from B. Can't occur, by assumption that E doesn't exist in ANCESTOR. */ /* (3) E exists in both ANCESTOR and B. Can't occur, by assumption that E doesn't exist in ancestor. */ } /* (5) E doesn't exist in ANCESTOR, and has been added to A. */ { /* (1) E doesn't exist in ANCESTOR, and has been added to B. Conflict. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[4], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_fs_make_file(txn_root, "theta", pool)); SVN_ERR(svn_test__set_file_contents (txn_root, "theta", "This is another file 'theta'.\n", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, "/theta", pool)); SVN_ERR(svn_fs_abort_txn(txn, pool)); /* (1) E exists in ANCESTOR, but has been deleted from B. Can't occur, by assumption that E doesn't exist in ANCESTOR. */ /* (3) E exists in both ANCESTOR and B. Can't occur, by assumption that E doesn't exist in ANCESTOR. */ } /* (4) E exists in ANCESTOR, but has been deleted from A */ { /* (1) E exists in ANCESTOR, but has been deleted from B. If neither delete was a result of a rename, then omit E from the merged tree. Otherwise, conflict. */ /* ### cmpilato todo: the rename case isn't actually handled by merge yet, so we know we won't get a conflict here. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_fs_delete(txn_root, "A/D/H", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, NULL, pool)); /*********************************************************************/ /* REVISION 6 */ /*********************************************************************/ { static svn_test__tree_entry_t expected_entries[] = { /* path, contents (0 = dir) */ { "theta", "This is the file 'theta'.\n" }, { "A", 0 }, { "A/mu", "This is the file 'mu'.\n" }, { "A/B", 0 }, { "A/B/lambda", "This is the file 'lambda'.\n" }, { "A/B/E", 0 }, { "A/B/E/alpha", "This is the file 'alpha'.\n" }, { "A/B/E/beta", "This is the file 'beta'.\n" }, { "A/B/F", 0 }, { "A/C", 0 }, { "A/C/kappa", "This is the file 'kappa'.\n" }, { "A/D", 0 }, { "A/D/gamma", "This is the file 'gamma'.\n" }, { "A/D/G", 0 }, { "A/D/G/pi", "This is the file 'pi'.\n" }, { "A/D/G/rho", "This is the file 'rho'.\n" }, { "A/D/G/tau", "This is the file 'tau'.\n" }, { "A/D/I", 0 }, { "A/D/I/delta", "This is the file 'delta'.\n" }, { "A/D/I/epsilon", "This is the file 'epsilon'.\n" } }; SVN_ERR(svn_fs_revision_root(&revision_root, fs, after_rev, pool)); SVN_ERR(svn_test__validate_tree(revision_root, expected_entries, 20, pool)); } revisions[revision_count++] = after_rev; /* Try deleting a file F inside a subtree S where S does not exist in the most recent revision, but does exist in the ancestor tree. This should conflict. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_fs_delete(txn_root, "A/D/H/omega", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, "/A/D/H", pool)); SVN_ERR(svn_fs_abort_txn(txn, pool)); /* E exists in both ANCESTOR and B ... */ { /* (1) but refers to different nodes. Conflict. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_fs_delete(txn_root, "A/D/H", pool)); SVN_ERR(svn_fs_make_dir(txn_root, "A/D/H", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, NULL, pool)); revisions[revision_count++] = after_rev; /*********************************************************************/ /* REVISION 7 */ /*********************************************************************/ /* Re-remove A/D/H because future tests expect it to be absent. */ { SVN_ERR(svn_fs_begin_txn (&txn, fs, revisions[revision_count - 1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_fs_delete(txn_root, "A/D/H", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, NULL, pool)); revisions[revision_count++] = after_rev; } /*********************************************************************/ /* REVISION 8 (looks exactly like revision 6, we hope) */ /*********************************************************************/ /* (1) but refers to different revisions of the same node. Conflict. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_fs_make_file(txn_root, "A/D/H/zeta", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, "/A/D/H", pool)); SVN_ERR(svn_fs_abort_txn(txn, pool)); /* (1) and refers to the same node revision. Omit E from the merged tree. This is already tested in Merge-Test 3 (A/D/H/chi, A/D/H/psi, e.g.), but we'll test it here again anyway. A little paranoia never hurt anyone. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_fs_delete(txn_root, "A/mu", pool)); /* unrelated change */ SVN_ERR(test_commit_txn(&after_rev, txn, NULL, pool)); /*********************************************************************/ /* REVISION 9 */ /*********************************************************************/ { static svn_test__tree_entry_t expected_entries[] = { /* path, contents (0 = dir) */ { "theta", "This is the file 'theta'.\n" }, { "A", 0 }, { "A/B", 0 }, { "A/B/lambda", "This is the file 'lambda'.\n" }, { "A/B/E", 0 }, { "A/B/E/alpha", "This is the file 'alpha'.\n" }, { "A/B/E/beta", "This is the file 'beta'.\n" }, { "A/B/F", 0 }, { "A/C", 0 }, { "A/C/kappa", "This is the file 'kappa'.\n" }, { "A/D", 0 }, { "A/D/gamma", "This is the file 'gamma'.\n" }, { "A/D/G", 0 }, { "A/D/G/pi", "This is the file 'pi'.\n" }, { "A/D/G/rho", "This is the file 'rho'.\n" }, { "A/D/G/tau", "This is the file 'tau'.\n" }, { "A/D/I", 0 }, { "A/D/I/delta", "This is the file 'delta'.\n" }, { "A/D/I/epsilon", "This is the file 'epsilon'.\n" } }; SVN_ERR(svn_fs_revision_root(&revision_root, fs, after_rev, pool)); SVN_ERR(svn_test__validate_tree(revision_root, expected_entries, 19, pool)); } revisions[revision_count++] = after_rev; } } /* Preparation for upcoming tests. We make a new head revision, with A/mu restored, but containing slightly different contents than its first incarnation. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[revision_count-1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_fs_make_file(txn_root, "A/mu", pool)); SVN_ERR(svn_test__set_file_contents (txn_root, "A/mu", "A new file 'mu'.\n", pool)); SVN_ERR(svn_fs_make_file(txn_root, "A/D/G/xi", pool)); SVN_ERR(svn_test__set_file_contents (txn_root, "A/D/G/xi", "This is the file 'xi'.\n", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, NULL, pool)); /*********************************************************************/ /* REVISION 10 */ /*********************************************************************/ { static svn_test__tree_entry_t expected_entries[] = { /* path, contents (0 = dir) */ { "theta", "This is the file 'theta'.\n" }, { "A", 0 }, { "A/mu", "A new file 'mu'.\n" }, { "A/B", 0 }, { "A/B/lambda", "This is the file 'lambda'.\n" }, { "A/B/E", 0 }, { "A/B/E/alpha", "This is the file 'alpha'.\n" }, { "A/B/E/beta", "This is the file 'beta'.\n" }, { "A/B/F", 0 }, { "A/C", 0 }, { "A/C/kappa", "This is the file 'kappa'.\n" }, { "A/D", 0 }, { "A/D/gamma", "This is the file 'gamma'.\n" }, { "A/D/G", 0 }, { "A/D/G/pi", "This is the file 'pi'.\n" }, { "A/D/G/rho", "This is the file 'rho'.\n" }, { "A/D/G/tau", "This is the file 'tau'.\n" }, { "A/D/G/xi", "This is the file 'xi'.\n" }, { "A/D/I", 0 }, { "A/D/I/delta", "This is the file 'delta'.\n" }, { "A/D/I/epsilon", "This is the file 'epsilon'.\n" } }; SVN_ERR(svn_fs_revision_root(&revision_root, fs, after_rev, pool)); SVN_ERR(svn_test__validate_tree(revision_root, expected_entries, 21, pool)); } revisions[revision_count++] = after_rev; /* (3) E exists in both ANCESTOR and A, but refers to different nodes. */ { /* (1) E exists in both ANCESTOR and B, but refers to different nodes, and not all nodes are directories. Conflict. */ /* ### kff todo: A/mu's contents will be exactly the same. If the fs ever starts optimizing this case, these tests may start to fail. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_fs_delete(txn_root, "A/mu", pool)); SVN_ERR(svn_fs_make_file(txn_root, "A/mu", pool)); SVN_ERR(svn_test__set_file_contents (txn_root, "A/mu", "This is the file 'mu'.\n", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, "/A/mu", pool)); SVN_ERR(svn_fs_abort_txn(txn, pool)); /* (1) E exists in both ANCESTOR and B, but refers to different revisions of the same node. Conflict. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_test__set_file_contents (txn_root, "A/mu", "A change to file 'mu'.\n", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, "/A/mu", pool)); SVN_ERR(svn_fs_abort_txn(txn, pool)); /* (1) E exists in both ANCESTOR and B, and refers to the same node revision. Replace E with A's node revision. */ { svn_stringbuf_t *old_mu_contents; SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_test__get_file_contents (txn_root, "A/mu", &old_mu_contents, pool)); if ((! old_mu_contents) || (strcmp(old_mu_contents->data, "This is the file 'mu'.\n") != 0)) { return svn_error_create (SVN_ERR_FS_GENERAL, NULL, "got wrong contents from an old revision tree"); } SVN_ERR(svn_fs_make_file(txn_root, "A/sigma", pool)); SVN_ERR(svn_test__set_file_contents /* unrelated change */ (txn_root, "A/sigma", "This is the file 'sigma'.\n", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, NULL, pool)); /*********************************************************************/ /* REVISION 11 */ /*********************************************************************/ { static svn_test__tree_entry_t expected_entries[] = { /* path, contents (0 = dir) */ { "theta", "This is the file 'theta'.\n" }, { "A", 0 }, { "A/mu", "A new file 'mu'.\n" }, { "A/sigma", "This is the file 'sigma'.\n" }, { "A/B", 0 }, { "A/B/lambda", "This is the file 'lambda'.\n" }, { "A/B/E", 0 }, { "A/B/E/alpha", "This is the file 'alpha'.\n" }, { "A/B/E/beta", "This is the file 'beta'.\n" }, { "A/B/F", 0 }, { "A/C", 0 }, { "A/C/kappa", "This is the file 'kappa'.\n" }, { "A/D", 0 }, { "A/D/gamma", "This is the file 'gamma'.\n" }, { "A/D/G", 0 }, { "A/D/G/pi", "This is the file 'pi'.\n" }, { "A/D/G/rho", "This is the file 'rho'.\n" }, { "A/D/G/tau", "This is the file 'tau'.\n" }, { "A/D/G/xi", "This is the file 'xi'.\n" }, { "A/D/I", 0 }, { "A/D/I/delta", "This is the file 'delta'.\n" }, { "A/D/I/epsilon", "This is the file 'epsilon'.\n" } }; SVN_ERR(svn_fs_revision_root(&revision_root, fs, after_rev, pool)); SVN_ERR(svn_test__validate_tree(revision_root, expected_entries, 22, pool)); } revisions[revision_count++] = after_rev; } } /* Preparation for upcoming tests. We make a new head revision. There are two changes in the new revision: A/B/lambda has been modified. We will also use the recent addition of A/D/G/xi, treated as a modification to A/D/G. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[revision_count-1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_test__set_file_contents (txn_root, "A/B/lambda", "Change to file 'lambda'.\n", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, NULL, pool)); /*********************************************************************/ /* REVISION 12 */ /*********************************************************************/ { static svn_test__tree_entry_t expected_entries[] = { /* path, contents (0 = dir) */ { "theta", "This is the file 'theta'.\n" }, { "A", 0 }, { "A/mu", "A new file 'mu'.\n" }, { "A/sigma", "This is the file 'sigma'.\n" }, { "A/B", 0 }, { "A/B/lambda", "Change to file 'lambda'.\n" }, { "A/B/E", 0 }, { "A/B/E/alpha", "This is the file 'alpha'.\n" }, { "A/B/E/beta", "This is the file 'beta'.\n" }, { "A/B/F", 0 }, { "A/C", 0 }, { "A/C/kappa", "This is the file 'kappa'.\n" }, { "A/D", 0 }, { "A/D/gamma", "This is the file 'gamma'.\n" }, { "A/D/G", 0 }, { "A/D/G/pi", "This is the file 'pi'.\n" }, { "A/D/G/rho", "This is the file 'rho'.\n" }, { "A/D/G/tau", "This is the file 'tau'.\n" }, { "A/D/G/xi", "This is the file 'xi'.\n" }, { "A/D/I", 0 }, { "A/D/I/delta", "This is the file 'delta'.\n" }, { "A/D/I/epsilon", "This is the file 'epsilon'.\n" } }; SVN_ERR(svn_fs_revision_root(&revision_root, fs, after_rev, pool)); SVN_ERR(svn_test__validate_tree(revision_root, expected_entries, 22, pool)); } revisions[revision_count++] = after_rev; /* (2) E exists in both ANCESTOR and A, but refers to different revisions of the same node. */ { /* (1a) E exists in both ANCESTOR and B, but refers to different revisions of the same file node. Conflict. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); SVN_ERR(svn_test__set_file_contents (txn_root, "A/B/lambda", "A different change to 'lambda'.\n", pool)); SVN_ERR(test_commit_txn(&after_rev, txn, "/A/B/lambda", pool)); SVN_ERR(svn_fs_abort_txn(txn, pool)); /* (1b) E exists in both ANCESTOR and B, but refers to different revisions of the same directory node. Merge A/E and B/E, recursively. Succeed, because no conflict beneath E. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, revisions[1], pool));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -