コード例 #1
0
ファイル: test_init.py プロジェクト: OrangeOranges/sno
def test_import_replace_existing_with_column_renames(
    data_archive,
    tmp_path,
    cli_runner,
    chdir,
    geopackage,
):
    with data_archive("gpkg-polygons") as data:
        repo_path = tmp_path / "emptydir"
        r = cli_runner.invoke(["init", repo_path])
        assert r.exit_code == 0
        with chdir(repo_path):
            r = cli_runner.invoke([
                "import",
                data / "nz-waca-adjustments.gpkg",
                "nz_waca_adjustments:mytable",
            ])
            assert r.exit_code == 0, r.stderr

            # Now reanme
            # * doesn't include the `survey_reference` column
            # * has the columns in a different order
            # * has a new column
            db = geopackage(data / "nz-waca-adjustments.gpkg")
            dbcur = db.cursor()
            dbcur.execute("""
                ALTER TABLE nz_waca_adjustments RENAME COLUMN survey_reference TO renamed_survey_reference;
                """)

            r = cli_runner.invoke([
                "import",
                "--replace-existing",
                data / "nz-waca-adjustments.gpkg",
                "nz_waca_adjustments:mytable",
            ])
            assert r.exit_code == 0, r.stderr
            r = cli_runner.invoke(["show", "-o", "json"])
            assert r.exit_code == 0, r.stderr
            diff = json.loads(r.stdout)["sno.diff/v1+hexwkb"]["mytable"]

            # The schema changed, but the features didn't.
            assert diff["meta"]["schema.json"]
            assert not diff.get("feature")

            repo = pygit2.Repository(str(repo_path))
            head_rs = RepositoryStructure.lookup(repo, "HEAD")
            old_rs = RepositoryStructure.lookup(repo, "HEAD^")
            assert head_rs.tree != old_rs.tree
            new_feature_tree = head_rs.tree / "mytable/.sno-dataset/feature"
            old_feature_tree = old_rs.tree / "mytable/.sno-dataset/feature"
            assert new_feature_tree == old_feature_tree
コード例 #2
0
ファイル: test_resolve.py プロジェクト: OrangeOranges/sno
def test_resolve_with_version(repo_version, create_conflicts, cli_runner):
    with create_conflicts(H.POLYGONS, repo_version) as repo:
        r = cli_runner.invoke(["merge", "theirs_branch", "-o", "json"])
        assert r.exit_code == 0, r
        assert json.loads(r.stdout)["sno.merge/v1"]["conflicts"]
        assert RepoState.get_state(repo) == RepoState.MERGING

        # Can't just complete the merge until we resolve the conflicts.
        r = cli_runner.invoke(["merge", "--continue"])
        assert r.exit_code == INVALID_OPERATION

        conflict_ids = get_conflict_ids(cli_runner)
        resolutions = iter(["ancestor", "ours", "theirs", "delete"])

        # Keep track of which order we resolve the conflicts - each conflict
        # resolved will have a primary key, and we resolve conflicts in
        # primary key order, but the primary keys are not contiguous.
        pk_order = []
        # Each conflict also has an internal "conflict" key - just its index
        # in the original list of conflicts - these are contiguous, but
        # we don't necessarily resolve the conflicts in this order.
        ck_order = []

        while conflict_ids:
            num_conflicts = len(conflict_ids)
            conflict_id = conflict_ids[0]
            pk = conflict_id.split(":", 2)[2]
            pk_order += [pk]

            r = cli_runner.invoke(
                ["resolve", conflict_id, f"--with={next(resolutions)}"])
            assert r.exit_code == 0, r
            conflict_ids = get_conflict_ids(cli_runner)
            assert len(conflict_ids) == num_conflicts - 1

            resolved_keys = MergeIndex.read_from_repo(repo).resolves.keys()
            ck_order += [k for k in resolved_keys if k not in ck_order]

        assert len(conflict_ids) == 0

        merge_index = MergeIndex.read_from_repo(repo)
        assert len(merge_index.entries) == 242
        assert len(merge_index.conflicts) == 4
        assert len(merge_index.resolves) == 4

        ck0, ck1, ck2, ck3 = ck_order
        # Conflict ck0 is resolved to ancestor, but the ancestor is None.
        assert merge_index.resolves[ck0] == []
        assert merge_index.conflicts[ck0].ancestor is None
        assert merge_index.resolves[ck1] == [merge_index.conflicts[ck1].ours]
        assert merge_index.resolves[ck2] == [merge_index.conflicts[ck2].theirs]
        assert merge_index.resolves[ck3] == []

        r = cli_runner.invoke(["merge", "--continue", "-m", "merge commit"])
        assert r.exit_code == 0, r
        assert repo.head.peel(pygit2.Commit).message == "merge commit"
        assert RepoState.get_state(repo) != RepoState.MERGING

        merged = RepositoryStructure.lookup(repo, "HEAD")
        ours = RepositoryStructure.lookup(repo, "ours_branch")
        theirs = RepositoryStructure.lookup(repo, "theirs_branch")
        l = H.POLYGONS.LAYER

        pk0, pk1, pk2, pk3 = pk_order
        # Feature at pk0 was resolved to ancestor, which was None.
        assert get_json_feature(merged, l, pk0) is None
        assert get_json_feature(merged, l,
                                pk1) == get_json_feature(ours, l, pk1)
        assert get_json_feature(merged, l,
                                pk2) == get_json_feature(theirs, l, pk2)
        assert get_json_feature(merged, l, pk3) is None
コード例 #3
0
ファイル: test_init.py プロジェクト: OrangeOranges/sno
def test_import_replace_existing_with_compatible_schema_changes(
    data_archive,
    tmp_path,
    cli_runner,
    chdir,
    geopackage,
):
    with data_archive("gpkg-polygons") as data:
        repo_path = tmp_path / "emptydir"
        r = cli_runner.invoke(["init", repo_path])
        assert r.exit_code == 0
        with chdir(repo_path):
            r = cli_runner.invoke([
                "import",
                data / "nz-waca-adjustments.gpkg",
                "nz_waca_adjustments:mytable",
            ])
            assert r.exit_code == 0, r.stderr

            # Now replace with a table which
            # * doesn't include the `survey_reference` column
            # * has the columns in a different order
            # * has a new column
            db = geopackage(data / "nz-waca-adjustments.gpkg")
            dbcur = db.cursor()
            dbcur.execute("""
                    CREATE TABLE IF NOT EXISTS "nz_waca_adjustments_2" (
                        "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
                        "geom" MULTIPOLYGON,
                        "date_adjusted" DATETIME,
                        "adjusted_nodes" MEDIUMINT,
                        "newcolumn" TEXT
                    );
                    INSERT INTO nz_waca_adjustments_2 (id, geom, date_adjusted, adjusted_nodes, newcolumn)
                        SELECT id, geom, date_adjusted, adjusted_nodes, NULL FROM nz_waca_adjustments
                    ;
                    DROP TABLE nz_waca_adjustments;
                    ALTER TABLE nz_waca_adjustments_2 RENAME TO nz_waca_adjustments;
                """)

            r = cli_runner.invoke([
                "import",
                "--replace-existing",
                data / "nz-waca-adjustments.gpkg",
                "nz_waca_adjustments:mytable",
            ])
            assert r.exit_code == 0, r.stderr
            r = cli_runner.invoke(["show", "-o", "json"])
            assert r.exit_code == 0, r.stderr
            diff = json.loads(r.stdout)["sno.diff/v1+hexwkb"]["mytable"]

            # The schema changed, but the features didn't.
            assert diff["meta"]["schema.json"]
            assert not diff.get("feature")

            repo = pygit2.Repository(str(repo_path))
            head_rs = RepositoryStructure.lookup(repo, "HEAD")
            old_rs = RepositoryStructure.lookup(repo, "HEAD^")
            assert head_rs.tree != old_rs.tree
            new_feature_tree = head_rs.tree / "mytable/.sno-dataset/feature"
            old_feature_tree = old_rs.tree / "mytable/.sno-dataset/feature"
            assert new_feature_tree == old_feature_tree
コード例 #4
0
ファイル: test_resolve.py プロジェクト: OrangeOranges/sno
def test_resolve_with_file(repo_version, create_conflicts, cli_runner):
    with create_conflicts(H.POLYGONS, repo_version) as repo:
        r = cli_runner.invoke(
            ["diff", "ancestor_branch..ours_branch", "-o", "geojson"])
        assert r.exit_code == 0, r
        ours_geojson = json.loads(r.stdout)["features"][0]
        assert ours_geojson["id"] == "I::98001"

        r = cli_runner.invoke(
            ["diff", "ancestor_branch..theirs_branch", "-o", "geojson"])
        assert r.exit_code == 0, r
        theirs_geojson = json.loads(r.stdout)["features"][0]
        assert theirs_geojson["id"] == "I::98001"

        r = cli_runner.invoke(["merge", "theirs_branch", "-o", "json"])
        assert r.exit_code == 0, r
        assert json.loads(r.stdout)["sno.merge/v1"]["conflicts"]

        r = cli_runner.invoke(["conflicts", "-s", "-o", "json"])
        assert r.exit_code == 0, r

        conflicts = json.loads(r.stdout)["sno.conflicts/v1"]
        add_add_conflict_pk = conflicts[H.POLYGONS.LAYER]["feature"][0]
        assert add_add_conflict_pk == 98001

        # These IDs are irrelevant, but we change them to at least be unique.
        ours_geojson["id"] = "ours-feature"
        theirs_geojson["id"] = "theirs-feature"
        # Changing this ID means the two features no long conflict.
        theirs_geojson["properties"]["id"] = 98002

        resolution = {
            "features": [ours_geojson, theirs_geojson],
            "type": "FeatureCollection",
        }
        write_repo_file(repo, "resolution.geojson", json.dumps(resolution))
        r = cli_runner.invoke([
            "resolve",
            f"{H.POLYGONS.LAYER}:feature:98001",
            "--with-file=resolution.geojson",
        ])
        assert r.exit_code == 0, r

        merge_index = MergeIndex.read_from_repo(repo)
        assert len(merge_index.entries) == 242
        assert len(merge_index.conflicts) == 4
        assert len(merge_index.resolves) == 1

        ck = next(iter(merge_index.resolves.keys()))
        assert len(merge_index.resolves[ck]) == 2  # Resolved with 2 features

        delete_remaining_conflicts(cli_runner)

        r = cli_runner.invoke(["merge", "--continue", "-m", "merge commit"])
        assert r.exit_code == 0, r
        assert repo.head.peel(pygit2.Commit).message == "merge commit"
        assert RepoState.get_state(repo) != RepoState.MERGING

        merged = RepositoryStructure.lookup(repo, "HEAD")
        ours = RepositoryStructure.lookup(repo, "ours_branch")
        theirs = RepositoryStructure.lookup(repo, "theirs_branch")
        l = H.POLYGONS.LAYER

        # Both features are present in the merged repo, ours at 98001 and theirs at 98002.
        assert get_json_feature(merged, l,
                                98001) == get_json_feature(ours, l, 98001)
        # Theirs feature is slightly different - it has a new primary key.
        assert get_json_feature(merged, l, 98002) != get_json_feature(
            theirs, l, 98001)

        modified_theirs_json = get_json_feature(theirs, l, 98001)
        modified_theirs_json["id"] = 98002
        assert get_json_feature(merged, l, 98002) == modified_theirs_json