abstra 3.24.0__py3-none-any.whl → 3.24.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- abstra/cli.py +8 -2
- {abstra-3.24.0.dist-info → abstra-3.24.2.dist-info}/METADATA +1 -2
- {abstra-3.24.0.dist-info → abstra-3.24.2.dist-info}/RECORD +205 -209
- abstra_internals/cloud_api/__init__.py +17 -8
- abstra_internals/contracts_generated.py +975 -707
- abstra_internals/controllers/ai.py +89 -1
- abstra_internals/controllers/git.py +6 -2
- abstra_internals/controllers/main.py +1 -1
- abstra_internals/interface/cli/editor.py +2 -2
- abstra_internals/repositories/git/__init__.py +1 -14
- abstra_internals/repositories/git/git_test.py +9 -1216
- abstra_internals/repositories/git/native.py +13 -7
- abstra_internals/repositories/git/types.py +7 -1
- abstra_internals/server/routes/git.py +11 -2
- abstra_statics/dist/assets/AbstraButton.vue_vue_type_script_setup_true_lang.a3ba2a31.js +2 -0
- abstra_statics/dist/assets/AbstraLogo.vue_vue_type_script_setup_true_lang.b1a71740.js +2 -0
- abstra_statics/dist/assets/ApiKeys.dafa1dc2.js +2 -0
- abstra_statics/dist/assets/App.45396b70.js +2 -0
- abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.db5596a1.js +2 -0
- abstra_statics/dist/assets/BaseLayout.135a51d9.js +2 -0
- abstra_statics/dist/assets/Billing.622c9155.js +2 -0
- abstra_statics/dist/assets/{Breadcrumb.26dec5f7.js → Breadcrumb.8a82fa01.js} +3 -3
- abstra_statics/dist/assets/Builds.38c0f966.css +1 -0
- abstra_statics/dist/assets/Builds.c3fd9633.js +2 -0
- abstra_statics/dist/assets/{Card.6cfffb80.js → Card.38a860a4.js} +5 -5
- abstra_statics/dist/assets/{CircularLoading.a13d6a76.js → CircularLoading.217756fb.js} +2 -2
- abstra_statics/dist/assets/CloseCircleOutlined.4c4707d8.js +2 -0
- abstra_statics/dist/assets/ConnectorsView.121898a9.js +2 -0
- abstra_statics/dist/assets/ConnectorsView.b594798e.css +1 -0
- abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.502d779a.js +2 -0
- abstra_statics/dist/assets/ContentLayout.b1c94c2b.js +2 -0
- abstra_statics/dist/assets/CrudView.75a430a4.js +2 -0
- abstra_statics/dist/assets/CrudView.8abe5bc2.css +1 -0
- abstra_statics/dist/assets/DocsButton.vue_vue_type_script_setup_true_lang.a9c8118b.js +2 -0
- abstra_statics/dist/assets/EditorLogin.fba78ce9.js +2 -0
- abstra_statics/dist/assets/EditorsView.1a9ccb13.js +2 -0
- abstra_statics/dist/assets/EnvVars.d77957ea.js +2 -0
- abstra_statics/dist/assets/Error.5bd293cc.js +2 -0
- abstra_statics/dist/assets/ExclamationCircleOutlined.5d5c3f30.js +2 -0
- abstra_statics/dist/assets/Files.39b07d88.css +1 -0
- abstra_statics/dist/assets/Files.c4ce443f.js +2 -0
- abstra_statics/dist/assets/Form.a4787001.js +2 -0
- abstra_statics/dist/assets/{FormRunner.46f6426d.css → FormRunner.1e6e7d2a.css} +1 -1
- abstra_statics/dist/assets/FormRunner.73650f9e.js +2 -0
- abstra_statics/dist/assets/Home.19a2303b.js +2 -0
- abstra_statics/dist/assets/Home.4eff6ce9.js +2 -0
- abstra_statics/dist/assets/Home.e8bf9440.css +1 -0
- abstra_statics/dist/assets/LoadingContainer.97fa8f2e.js +2 -0
- abstra_statics/dist/assets/LoadingOutlined.e309ab16.js +2 -0
- abstra_statics/dist/assets/Login.632cada3.js +2 -0
- abstra_statics/dist/assets/{Login.75d13f6c.css → Login.ac75228f.css} +1 -1
- abstra_statics/dist/assets/Login.ecec1ff2.js +2 -0
- abstra_statics/dist/assets/Login.vue_vue_type_script_setup_true_lang.ada1c6c9.js +2 -0
- abstra_statics/dist/assets/Logo.d77d5637.js +2 -0
- abstra_statics/dist/assets/Logs.c1f01b05.js +2 -0
- abstra_statics/dist/assets/LogsController.0ff97ed4.css +1 -0
- abstra_statics/dist/assets/LogsController.2dceb3d3.js +2 -0
- abstra_statics/dist/assets/Main.44b7640e.js +2 -0
- abstra_statics/dist/assets/{MockForm.deda9355.js → MockForm.9b7a0df3.js} +2 -2
- abstra_statics/dist/assets/Navbar.0951ed6d.js +2 -0
- abstra_statics/dist/assets/Navbar.61d3e0a6.css +1 -0
- abstra_statics/dist/assets/NewEditor.d65a400f.js +8 -0
- abstra_statics/dist/assets/NewEditor.e3cfeb2c.css +1 -0
- abstra_statics/dist/assets/OidcLoginCallback.66b0f38a.js +2 -0
- abstra_statics/dist/assets/OidcLogoutCallback.48d8429a.js +2 -0
- abstra_statics/dist/assets/OmniChat.60ee26c8.css +1 -0
- abstra_statics/dist/assets/OmniChat.c3de8733.js +6 -0
- abstra_statics/dist/assets/OnboardingView.6cda1bc5.js +2 -0
- abstra_statics/dist/assets/OnboardingView.e871e6d8.css +1 -0
- abstra_statics/dist/assets/Organization.c36206b7.js +2 -0
- abstra_statics/dist/assets/Organizations.2b1c6c65.js +2 -0
- abstra_statics/dist/assets/{PhArrowCounterClockwise.vue.8090d021.js → PhArrowCounterClockwise.vue.9e570570.js} +2 -2
- abstra_statics/dist/assets/{PhArrowSquareOut.vue.26582195.js → PhArrowSquareOut.vue.bcbdb6e7.js} +2 -2
- abstra_statics/dist/assets/{PhClockCounterClockwise.vue.812311ad.js → PhClockCounterClockwise.vue.4bd682d8.js} +2 -2
- abstra_statics/dist/assets/{PhCopy.vue.59b0f1b4.js → PhCopy.vue.29934bc2.js} +2 -2
- abstra_statics/dist/assets/PhCopySimple.vue.0241af8c.js +2 -0
- abstra_statics/dist/assets/{PhCube.vue.63ae7d32.js → PhCube.vue.0fe2c514.js} +2 -2
- abstra_statics/dist/assets/PhDatabase.vue.fdfb515c.js +2 -0
- abstra_statics/dist/assets/{PhDotsThreeVertical.vue.ab4580a5.js → PhDotsThreeVertical.vue.7a0e0638.js} +2 -2
- abstra_statics/dist/assets/{PhDownloadSimple.vue.c2eaaad1.js → PhDownloadSimple.vue.f1245c40.js} +2 -2
- abstra_statics/dist/assets/PhFileArrowUp.vue.c292afe1.js +2 -0
- abstra_statics/dist/assets/PhFilePlus.vue.c39ff1a9.js +2 -0
- abstra_statics/dist/assets/{PhFolderPlus.vue.05ba4a5c.js → PhFolderPlus.vue.bc40161e.js} +2 -2
- abstra_statics/dist/assets/{PhGear.vue.0e4a6135.js → PhGear.vue.0feed515.js} +2 -2
- abstra_statics/dist/assets/{PhKey.vue.b2c184d1.js → PhKey.vue.15a9e64e.js} +2 -2
- abstra_statics/dist/assets/{PhPencil.vue.2f2fe576.js → PhPencil.vue.a7219766.js} +2 -2
- abstra_statics/dist/assets/PhPencilSimple.vue.15a2b403.js +2 -0
- abstra_statics/dist/assets/PhRocket.vue.7155b91f.js +2 -0
- abstra_statics/dist/assets/{PhSignOut.vue.a271f14b.js → PhSignOut.vue.2af17bd7.js} +2 -2
- abstra_statics/dist/assets/{PhSparkle.vue.726defa2.js → PhSparkle.vue.c7f06cac.js} +2 -2
- abstra_statics/dist/assets/PhTranslate.vue.2ce651a6.js +2 -0
- abstra_statics/dist/assets/{PhUsersThree.vue.275d13ab.js → PhUsersThree.vue.2942df75.js} +2 -2
- abstra_statics/dist/assets/{PhWarningCircle.vue.3b1aca1b.js → PhWarningCircle.vue.05a40bc4.js} +2 -2
- abstra_statics/dist/assets/PhWebhooksLogo.vue.e4752384.js +2 -0
- abstra_statics/dist/assets/PlayerConfigProvider.00af5968.js +2 -0
- abstra_statics/dist/assets/PlayerNavbar.117f184b.js +2 -0
- abstra_statics/dist/assets/{PlayerNavbar.77209eae.css → PlayerNavbar.4dc29a45.css} +1 -1
- abstra_statics/dist/assets/Project.66111161.js +2 -0
- abstra_statics/dist/assets/Project.9c418d2e.css +1 -0
- abstra_statics/dist/assets/ProjectLogin.d9bb1f86.js +2 -0
- abstra_statics/dist/assets/ProjectSettings.f8c6f60a.js +2 -0
- abstra_statics/dist/assets/ProjectsView.32f6ccff.js +2 -0
- abstra_statics/dist/assets/ProjectsView.e26ddfd5.css +1 -0
- abstra_statics/dist/assets/SaveButton.363ea20f.css +1 -0
- abstra_statics/dist/assets/SaveButton.c3f2a4bb.js +2 -0
- abstra_statics/dist/assets/ScrollArea.vue_vue_type_script_setup_true_lang.cb5567cd.js +2 -0
- abstra_statics/dist/assets/{Sidebar.29baeab0.css → Sidebar.161522da.css} +1 -1
- abstra_statics/dist/assets/Sidebar.1c4e35be.js +2 -0
- abstra_statics/dist/assets/Sql.6d9a778c.css +1 -0
- abstra_statics/dist/assets/Sql.8d31ec23.js +5 -0
- abstra_statics/dist/assets/Steps.687763a5.js +2 -0
- abstra_statics/dist/assets/TableCard.8c99a870.js +2 -0
- abstra_statics/dist/assets/{TableEditor.5853a363.css → TableEditor.20fecc75.css} +1 -1
- abstra_statics/dist/assets/TableEditor.ba7a8b6a.js +2 -0
- abstra_statics/dist/assets/Tables.113960f2.js +39 -0
- abstra_statics/dist/assets/TablesDiagram.8e6d1e89.js +15 -0
- abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.5cc96b0d.js +2 -0
- abstra_statics/dist/assets/Tasks.90846020.js +2 -0
- abstra_statics/dist/assets/{UploadOutlined.eab75eb0.js → UploadOutlined.518baf9a.js} +2 -2
- abstra_statics/dist/assets/View.ded6b355.js +2 -0
- abstra_statics/dist/assets/View.vue_vue_type_script_setup_true_lang.285b5e2c.js +2 -0
- abstra_statics/dist/assets/Watermark.5071a4b2.js +2 -0
- abstra_statics/dist/assets/WebEditor.18ece735.js +2 -0
- abstra_statics/dist/assets/WebEditor.b886e4d1.css +1 -0
- abstra_statics/dist/assets/WidgetPreview.88a4f27f.js +2 -0
- abstra_statics/dist/assets/WorkflowViewer.3b6aee8e.css +1 -0
- abstra_statics/dist/assets/WorkflowViewer.778c401d.js +2 -0
- abstra_statics/dist/assets/ant-design.4efc9ccd.js +2 -0
- abstra_statics/dist/assets/{apiKey.72f497ca.js → apiKey.bd946d8c.js} +2 -2
- abstra_statics/dist/assets/asyncComputed.7bc1692e.js +2 -0
- abstra_statics/dist/assets/{build.df2d55cc.js → build.a8637e29.js} +2 -2
- abstra_statics/dist/assets/colorHelpers.8ba18214.js +2 -0
- abstra_statics/dist/assets/{console.2bf7f04d.js → console.2a5ed51a.js} +4 -4
- abstra_statics/dist/assets/constants.534f67bc.js +2 -0
- abstra_statics/dist/assets/contracts.generated.8ad36e63.js +2 -0
- abstra_statics/dist/assets/{cssMode.7133c7cb.js → cssMode.6c4ccf50.js} +2 -2
- abstra_statics/dist/assets/{datetime.8de2ff28.js → datetime.89495471.js} +2 -2
- abstra_statics/dist/assets/dayjs.304f38f8.js +2 -0
- abstra_statics/dist/assets/editor.c1a1bd33.js +2 -0
- abstra_statics/dist/assets/editor.main.84e237cf.js +2 -0
- abstra_statics/dist/assets/fetch.452c58e5.js +2 -0
- abstra_statics/dist/assets/files.8999afd5.js +2 -0
- abstra_statics/dist/assets/{folder.d8e23009.js → folder.81ef8619.js} +2 -2
- abstra_statics/dist/assets/{freemarker2.6698d1ea.js → freemarker2.559f77f2.js} +2 -2
- abstra_statics/dist/assets/{handlebars.a6c42dc0.js → handlebars.8d101b7c.js} +2 -2
- abstra_statics/dist/assets/{html.493a5410.js → html.b3e7d3ab.js} +3 -3
- abstra_statics/dist/assets/{htmlMode.a28b2fca.js → htmlMode.2305b1bb.js} +2 -2
- abstra_statics/dist/assets/{index.fb49354b.js → index.71eb83f3.js} +2 -2
- abstra_statics/dist/assets/{index.79ce3bf1.js → index.90acf038.js} +2 -2
- abstra_statics/dist/assets/index.b74c262c.js +4 -0
- abstra_statics/dist/assets/index.bc97991a.js +2 -0
- abstra_statics/dist/assets/index.d809956c.js +2 -0
- abstra_statics/dist/assets/{index.57042181.css → index.da037bc0.css} +1 -1
- abstra_statics/dist/assets/index.da4f9d54.js +2 -0
- abstra_statics/dist/assets/{index.c34a405a.js → index.e5cb42a1.js} +2 -2
- abstra_statics/dist/assets/{index.5d6b1e62.js → index.f2beb20d.js} +2 -2
- abstra_statics/dist/assets/{index.4d20c159.js → index.f6171691.js} +3 -3
- abstra_statics/dist/assets/{javascript.3a36cf17.js → javascript.3000fc25.js} +3 -3
- abstra_statics/dist/assets/{jsonMode.bead6ac8.js → jsonMode.7bbb508d.js} +2 -2
- abstra_statics/dist/assets/{jwt-decode.9f7a5511.css → jwt-decode.c5760184.css} +2 -2
- abstra_statics/dist/assets/{jwt-decode.esm.d4517a10.js → jwt-decode.esm.c9c37cdc.js} +197 -197
- abstra_statics/dist/assets/{linters.2f3141cb.js → linters.7fec18d9.js} +2 -2
- abstra_statics/dist/assets/{liquid.0c337fae.js → liquid.b4ac9aaf.js} +3 -3
- abstra_statics/dist/assets/member.3c12efee.js +2 -0
- abstra_statics/dist/assets/metadata.e627ddda.js +2 -0
- abstra_statics/dist/assets/omniChatStore.508e8ece.js +9 -0
- abstra_statics/dist/assets/omniChatStore.b58e3bed.css +1 -0
- abstra_statics/dist/assets/{organization.928c9bef.js → organization.cd03f9a8.js} +2 -2
- abstra_statics/dist/assets/os.f08724fb.js +2 -0
- abstra_statics/dist/assets/player.7362caf4.js +2 -0
- abstra_statics/dist/assets/{plotly.min.7225d3a0.js → plotly.min.50ebb925.js} +2 -2
- abstra_statics/dist/assets/polling.4db5ee9a.js +2 -0
- abstra_statics/dist/assets/{project.619b7244.js → project.9a068e8d.js} +2 -2
- abstra_statics/dist/assets/{python.05764499.js → python.51a7c648.js} +3 -3
- abstra_statics/dist/assets/{razor.81a45581.js → razor.99323f5f.js} +3 -3
- abstra_statics/dist/assets/record.a33d29b1.js +2 -0
- abstra_statics/dist/assets/{redirect.f028a879.js → redirect.42bf4f0a.js} +2 -2
- abstra_statics/dist/assets/repository.5190b94f.js +2 -0
- abstra_statics/dist/assets/repository.94fb77c7.js +2 -0
- abstra_statics/dist/assets/repository.c0d70cb2.js +2 -0
- abstra_statics/dist/assets/router.4168cc71.js +2 -0
- abstra_statics/dist/assets/{router.424f7da9.js → router.a8616541.js} +5 -5
- abstra_statics/dist/assets/string.8fab6b53.js +2 -0
- abstra_statics/dist/assets/{tables.1f68ec62.js → tables.2e1c934b.js} +2 -2
- abstra_statics/dist/assets/tasksController.1feffcfe.js +4 -0
- abstra_statics/dist/assets/{toggleHighContrast.0d0e5662.js → toggleHighContrast.6544a728.js} +7 -7
- abstra_statics/dist/assets/{tsMode.6eadbf06.js → tsMode.922e04bb.js} +2 -2
- abstra_statics/dist/assets/{typescript.1670e287.js → typescript.1b4f8286.js} +3 -3
- abstra_statics/dist/assets/url.9e033350.js +2 -0
- abstra_statics/dist/assets/{useCodebaseEvents.53dec1f2.js → useCodebaseEvents.ffe057d1.js} +2 -2
- abstra_statics/dist/assets/useTables.5fffa3f1.js +2 -0
- abstra_statics/dist/assets/userStore.d962fba4.js +2 -0
- abstra_statics/dist/assets/uuid.8581bc03.js +2 -0
- abstra_statics/dist/assets/vue-flow-background.3e9183ec.js +2 -0
- abstra_statics/dist/assets/vue-flow-core.41c647da.js +22 -0
- abstra_statics/dist/assets/{vue-quill.esm-bundler.c4f04985.js → vue-quill.esm-bundler.36e79a95.js} +2 -2
- abstra_statics/dist/assets/{workspaceStore.6244d03d.js → workspaceStore.5a435520.js} +2 -2
- abstra_statics/dist/assets/{xml.f2867af8.js → xml.c1692f52.js} +3 -3
- abstra_statics/dist/assets/{yaml.5427bb1b.js → yaml.244444c1.js} +2 -2
- abstra_statics/dist/console.html +15 -15
- abstra_statics/dist/editor.html +15 -15
- abstra_statics/dist/player.html +10 -10
- abstra/connectors/banking/__init__.py +0 -0
- abstra/connectors/banking/brazil.py +0 -5
- abstra_internals/repositories/git/dulwich.py +0 -1353
- abstra_internals/services/banking/__init__.py +0 -3
- abstra_internals/services/banking/banking_service.py +0 -104
- abstra_internals/services/banking/client_factory.py +0 -70
- abstra_internals/services/banking/sdk/__init__.py +0 -0
- abstra_internals/services/banking/sdk/generate_totalbank_api.py +0 -383
- abstra_statics/dist/assets/AbstraButton.vue_vue_type_script_setup_true_lang.eb8ccb64.js +0 -2
- abstra_statics/dist/assets/AbstraLogo.vue_vue_type_script_setup_true_lang.9f98292e.js +0 -2
- abstra_statics/dist/assets/ApiKeys.e975c4f3.js +0 -2
- abstra_statics/dist/assets/App.f62faff6.js +0 -2
- abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.5aa45ac1.js +0 -2
- abstra_statics/dist/assets/BaseLayout.1ec2c96d.js +0 -2
- abstra_statics/dist/assets/Billing.60adc9fa.js +0 -2
- abstra_statics/dist/assets/Builds.ace9e3da.css +0 -1
- abstra_statics/dist/assets/Builds.f86210bc.js +0 -2
- abstra_statics/dist/assets/CloseCircleOutlined.30bc25a8.js +0 -2
- abstra_statics/dist/assets/ConnectorsView.33c5380f.css +0 -1
- abstra_statics/dist/assets/ConnectorsView.eb4c769f.js +0 -2
- abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.8d2e4672.js +0 -2
- abstra_statics/dist/assets/ContentLayout.d03fee5b.js +0 -2
- abstra_statics/dist/assets/CrudView.c0824225.js +0 -2
- abstra_statics/dist/assets/CrudView.e24590ae.css +0 -1
- abstra_statics/dist/assets/DocsButton.vue_vue_type_script_setup_true_lang.3668aee4.js +0 -2
- abstra_statics/dist/assets/EditorLogin.46db248f.js +0 -2
- abstra_statics/dist/assets/EditorsView.e72621fa.js +0 -2
- abstra_statics/dist/assets/EnvVars.f9f9d61f.js +0 -2
- abstra_statics/dist/assets/Error.864f05b3.js +0 -2
- abstra_statics/dist/assets/ExclamationCircleOutlined.a489b996.js +0 -2
- abstra_statics/dist/assets/Files.afe615e1.js +0 -2
- abstra_statics/dist/assets/Files.d0e8d2ff.css +0 -1
- abstra_statics/dist/assets/Form.556d0de2.js +0 -2
- abstra_statics/dist/assets/FormRunner.7f56a8c6.js +0 -2
- abstra_statics/dist/assets/Home.287d17f8.js +0 -2
- abstra_statics/dist/assets/Home.3794e8b4.css +0 -1
- abstra_statics/dist/assets/Home.5b7e9c23.js +0 -2
- abstra_statics/dist/assets/Live.37415b2d.css +0 -1
- abstra_statics/dist/assets/Live.50bacfea.js +0 -2
- abstra_statics/dist/assets/LoadingContainer.ebace8de.js +0 -2
- abstra_statics/dist/assets/LoadingOutlined.9e949112.js +0 -2
- abstra_statics/dist/assets/Login.536a3067.js +0 -2
- abstra_statics/dist/assets/Login.bec408c9.js +0 -2
- abstra_statics/dist/assets/Login.vue_vue_type_script_setup_true_lang.1c3f108d.js +0 -2
- abstra_statics/dist/assets/Logo.82d6ab70.js +0 -2
- abstra_statics/dist/assets/Logs.f6135084.js +0 -2
- abstra_statics/dist/assets/LogsController.6b666816.js +0 -2
- abstra_statics/dist/assets/LogsController.fb0d96c2.css +0 -1
- abstra_statics/dist/assets/Main.77b115f8.js +0 -2
- abstra_statics/dist/assets/Navbar.2dc6d02c.css +0 -1
- abstra_statics/dist/assets/Navbar.4a6f2b09.js +0 -2
- abstra_statics/dist/assets/NewEditor.5f84de86.css +0 -1
- abstra_statics/dist/assets/NewEditor.e558e47d.js +0 -8
- abstra_statics/dist/assets/OidcLoginCallback.7f514b45.js +0 -2
- abstra_statics/dist/assets/OidcLogoutCallback.038813a1.js +0 -2
- abstra_statics/dist/assets/OmniChat.05ba8d8a.css +0 -1
- abstra_statics/dist/assets/OmniChat.60d98deb.js +0 -6
- abstra_statics/dist/assets/OnboardingView.3996b08d.css +0 -1
- abstra_statics/dist/assets/OnboardingView.9413ee50.js +0 -2
- abstra_statics/dist/assets/Organization.7203cc0b.js +0 -2
- abstra_statics/dist/assets/Organizations.91220ca0.js +0 -2
- abstra_statics/dist/assets/PhBookBookmark.vue.5b7ab079.js +0 -2
- abstra_statics/dist/assets/PhChats.vue.b5df7174.js +0 -2
- abstra_statics/dist/assets/PhCopySimple.vue.d41d9160.js +0 -2
- abstra_statics/dist/assets/PhDatabase.vue.edfcb96b.js +0 -2
- abstra_statics/dist/assets/PhPencilSimple.vue.cc8620ae.js +0 -2
- abstra_statics/dist/assets/PhRocket.vue.e397203c.js +0 -2
- abstra_statics/dist/assets/PhUserList.vue.6a29f16d.js +0 -2
- abstra_statics/dist/assets/PhWebhooksLogo.vue.5e772aac.js +0 -2
- abstra_statics/dist/assets/PlayerConfigProvider.e90a2b41.js +0 -2
- abstra_statics/dist/assets/PlayerNavbar.11ec1844.js +0 -2
- abstra_statics/dist/assets/Project.9c75c141.css +0 -1
- abstra_statics/dist/assets/Project.c16740fb.js +0 -2
- abstra_statics/dist/assets/ProjectLogin.e7a6f444.js +0 -2
- abstra_statics/dist/assets/ProjectSettings.52c19693.js +0 -2
- abstra_statics/dist/assets/ProjectsView.16d8ecf6.css +0 -1
- abstra_statics/dist/assets/ProjectsView.22fa7a8e.js +0 -2
- abstra_statics/dist/assets/SaveButton.719393d2.js +0 -2
- abstra_statics/dist/assets/SaveButton.932ac6b8.css +0 -1
- abstra_statics/dist/assets/ScrollArea.vue_vue_type_script_setup_true_lang.d4028954.js +0 -2
- abstra_statics/dist/assets/Sidebar.5cb8e04e.js +0 -2
- abstra_statics/dist/assets/Sql.23d80bad.js +0 -5
- abstra_statics/dist/assets/Sql.90e6e2ba.css +0 -1
- abstra_statics/dist/assets/Steps.8e5d201a.js +0 -2
- abstra_statics/dist/assets/TableCard.59f95f8f.js +0 -2
- abstra_statics/dist/assets/TableEditor.8539f984.js +0 -2
- abstra_statics/dist/assets/Tables.44d953f7.js +0 -2
- abstra_statics/dist/assets/TablesDiagram.8e47383c.js +0 -15
- abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.6866fb32.js +0 -2
- abstra_statics/dist/assets/Tasks.09551b19.js +0 -2
- abstra_statics/dist/assets/View.5fd7ddf0.js +0 -2
- abstra_statics/dist/assets/View.vue_vue_type_script_setup_true_lang.a904f400.js +0 -2
- abstra_statics/dist/assets/Watermark.ab3d818f.js +0 -2
- abstra_statics/dist/assets/WebEditor.c2e271d1.css +0 -1
- abstra_statics/dist/assets/WebEditor.d6ec6392.js +0 -2
- abstra_statics/dist/assets/WidgetPreview.86b31dec.js +0 -2
- abstra_statics/dist/assets/ant-design.a865486e.js +0 -2
- abstra_statics/dist/assets/asyncComputed.cf5282fc.js +0 -2
- abstra_statics/dist/assets/colorHelpers.37d9932b.js +0 -2
- abstra_statics/dist/assets/constants.7d38ec8b.js +0 -2
- abstra_statics/dist/assets/contracts.generated.590b1102.js +0 -2
- abstra_statics/dist/assets/dayjs.f18bbbca.js +0 -2
- abstra_statics/dist/assets/editor.3a4714e3.js +0 -2
- abstra_statics/dist/assets/editor.main.9c635b9a.js +0 -2
- abstra_statics/dist/assets/fetch.89fd5b7b.js +0 -2
- abstra_statics/dist/assets/index.2af3391c.js +0 -4
- abstra_statics/dist/assets/index.4176fe88.js +0 -2
- abstra_statics/dist/assets/index.fb182bd1.js +0 -2
- abstra_statics/dist/assets/member.48d6f2cd.js +0 -2
- abstra_statics/dist/assets/metadata.c3aed6e1.js +0 -2
- abstra_statics/dist/assets/omniChatStore.c53bcca2.js +0 -8
- abstra_statics/dist/assets/omniChatStore.ec95fb81.css +0 -1
- abstra_statics/dist/assets/player.d3aeafc5.js +0 -2
- abstra_statics/dist/assets/polling.82ee6b45.js +0 -2
- abstra_statics/dist/assets/record.7f43486c.js +0 -2
- abstra_statics/dist/assets/repository.9534db4b.js +0 -2
- abstra_statics/dist/assets/repository.c15239ce.js +0 -2
- abstra_statics/dist/assets/router.262190ec.js +0 -2
- abstra_statics/dist/assets/string.0acf5572.js +0 -2
- abstra_statics/dist/assets/tasksController.371896de.js +0 -4
- abstra_statics/dist/assets/url.e8732f77.js +0 -2
- abstra_statics/dist/assets/useTables.4f034cf8.js +0 -2
- abstra_statics/dist/assets/userStore.31024da3.js +0 -2
- abstra_statics/dist/assets/uuid.bde15ce7.js +0 -2
- abstra_statics/dist/assets/vue-flow-background.818c7852.js +0 -2
- abstra_statics/dist/assets/vue-flow-core.1180ec83.js +0 -22
- {abstra-3.24.0.dist-info → abstra-3.24.2.dist-info}/WHEEL +0 -0
- {abstra-3.24.0.dist-info → abstra-3.24.2.dist-info}/entry_points.txt +0 -0
- {abstra-3.24.0.dist-info → abstra-3.24.2.dist-info}/top_level.txt +0 -0
|
@@ -1,41 +1,32 @@
|
|
|
1
1
|
import shutil
|
|
2
2
|
import tempfile
|
|
3
3
|
import unittest
|
|
4
|
-
from abc import ABC, abstractmethod
|
|
5
4
|
from pathlib import Path
|
|
6
|
-
from typing import
|
|
5
|
+
from typing import Optional
|
|
7
6
|
|
|
8
|
-
from abstra_internals.repositories.git.dulwich import DulwichGitRepository
|
|
9
7
|
from abstra_internals.repositories.git.native import NativeGitRepository
|
|
10
8
|
from abstra_internals.repositories.git.types import (
|
|
11
|
-
GitRepositoryInterface,
|
|
12
9
|
GitStatus,
|
|
13
10
|
)
|
|
14
11
|
|
|
15
12
|
|
|
16
|
-
class
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
__test__ = False
|
|
20
|
-
|
|
21
|
-
@property
|
|
22
|
-
@abstractmethod
|
|
23
|
-
def repo_class(self) -> Type[GitRepositoryInterface]:
|
|
24
|
-
"""The repository class to test"""
|
|
25
|
-
pass
|
|
13
|
+
class NativeGitRepositoryTest(unittest.TestCase):
|
|
14
|
+
"""Test suite for NativeGitRepository"""
|
|
26
15
|
|
|
27
16
|
def setUp(self):
|
|
28
17
|
"""Set up test environment"""
|
|
29
18
|
super().setUp()
|
|
30
19
|
self.temp_dir = Path(tempfile.mkdtemp())
|
|
31
|
-
self.repo =
|
|
20
|
+
self.repo = NativeGitRepository(self.temp_dir)
|
|
32
21
|
self._original_commit_changes = self.repo.commit_changes
|
|
33
22
|
self.repo.commit_changes = self._commit_changes_wrapper
|
|
34
23
|
|
|
35
|
-
def _commit_changes_wrapper(
|
|
24
|
+
def _commit_changes_wrapper(
|
|
25
|
+
self, message: str, author: Optional[str] = None
|
|
26
|
+
) -> bool:
|
|
36
27
|
"""Wrapper for commit_changes that ensures git is configured"""
|
|
37
28
|
self.ensure_git_configured()
|
|
38
|
-
return self._original_commit_changes(message,
|
|
29
|
+
return self._original_commit_changes(message, author)
|
|
39
30
|
|
|
40
31
|
def tearDown(self):
|
|
41
32
|
"""Clean up test environment"""
|
|
@@ -93,7 +84,7 @@ class _GitRepositoryTestBase(unittest.TestCase, ABC):
|
|
|
93
84
|
# Create subdirectory and test from there
|
|
94
85
|
sub_dir = self.temp_dir / "subdir"
|
|
95
86
|
sub_dir.mkdir()
|
|
96
|
-
sub_repo =
|
|
87
|
+
sub_repo = NativeGitRepository(sub_dir)
|
|
97
88
|
root = sub_repo.find_git_root()
|
|
98
89
|
if root:
|
|
99
90
|
# Resolve both paths to handle macOS symlinks (e.g., /var vs /private/var)
|
|
@@ -364,1209 +355,11 @@ class _GitRepositoryTestBase(unittest.TestCase, ABC):
|
|
|
364
355
|
self.assertEqual(file_content, "version 1")
|
|
365
356
|
|
|
366
357
|
|
|
367
|
-
class NativeGitRepositoryTest(_GitRepositoryTestBase):
|
|
368
|
-
"""Test suite for NativeGitRepository"""
|
|
369
|
-
|
|
370
|
-
# Override parent's __test__ = False to make this discoverable by pytest
|
|
371
|
-
__test__ = True
|
|
372
|
-
|
|
373
|
-
@property
|
|
374
|
-
def repo_class(self) -> Type[GitRepositoryInterface]:
|
|
375
|
-
return NativeGitRepository
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
class DulwichGitRepositoryTest(_GitRepositoryTestBase):
|
|
379
|
-
"""Test suite for DulwichGitRepository"""
|
|
380
|
-
|
|
381
|
-
__test__ = True
|
|
382
|
-
|
|
383
|
-
@property
|
|
384
|
-
def repo_class(self) -> Type[GitRepositoryInterface]:
|
|
385
|
-
return DulwichGitRepository
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
class GitImplementationComparisonTest(unittest.TestCase):
|
|
389
|
-
"""Test suite to compare both implementations and ensure they have identical behavior"""
|
|
390
|
-
|
|
391
|
-
def setUp(self):
|
|
392
|
-
"""Set up test environments for both implementations"""
|
|
393
|
-
super().setUp()
|
|
394
|
-
self.temp_dir1 = Path(tempfile.mkdtemp())
|
|
395
|
-
self.temp_dir2 = Path(tempfile.mkdtemp())
|
|
396
|
-
self.native_repo = NativeGitRepository(self.temp_dir1)
|
|
397
|
-
self.native_repo.configure_git_user("Test User", "test@example.com")
|
|
398
|
-
self.dulwich_repo = DulwichGitRepository(self.temp_dir2)
|
|
399
|
-
self.dulwich_repo.configure_git_user("Test User", "test@example.com")
|
|
400
|
-
|
|
401
|
-
# Wrap repo methods to auto-configure git when needed
|
|
402
|
-
self._setup_repo_wrapper(self.native_repo)
|
|
403
|
-
self._setup_repo_wrapper(self.dulwich_repo)
|
|
404
|
-
|
|
405
|
-
def _setup_repo_wrapper(self, repo):
|
|
406
|
-
"""Set up commit wrapper for a repository"""
|
|
407
|
-
original_commit = repo.commit_changes
|
|
408
|
-
|
|
409
|
-
def commit_wrapper(message: str) -> bool:
|
|
410
|
-
self._ensure_git_configured(repo)
|
|
411
|
-
return original_commit(message)
|
|
412
|
-
|
|
413
|
-
repo.commit_changes = commit_wrapper
|
|
414
|
-
|
|
415
|
-
def _ensure_git_configured(self, repo):
|
|
416
|
-
"""Ensure git is configured for commits (required in CI environments)"""
|
|
417
|
-
# Check if user is already configured
|
|
418
|
-
if not repo.get_git_config("user.name"):
|
|
419
|
-
repo.set_git_config("user.name", "Test User")
|
|
420
|
-
if not repo.get_git_config("user.email"):
|
|
421
|
-
repo.set_git_config("user.email", "test@example.com")
|
|
422
|
-
|
|
423
|
-
def tearDown(self):
|
|
424
|
-
"""Clean up test environments"""
|
|
425
|
-
super().tearDown()
|
|
426
|
-
for temp_dir in [self.temp_dir1, self.temp_dir2]:
|
|
427
|
-
if temp_dir and temp_dir.exists():
|
|
428
|
-
shutil.rmtree(temp_dir, ignore_errors=True)
|
|
429
|
-
|
|
430
|
-
def _create_identical_file(self, filename: str, content: str) -> Tuple[Path, Path]:
|
|
431
|
-
"""Create identical files in both test directories"""
|
|
432
|
-
file1 = self.temp_dir1 / filename
|
|
433
|
-
file2 = self.temp_dir2 / filename
|
|
434
|
-
|
|
435
|
-
file1.parent.mkdir(parents=True, exist_ok=True)
|
|
436
|
-
file2.parent.mkdir(parents=True, exist_ok=True)
|
|
437
|
-
|
|
438
|
-
file1.write_text(content)
|
|
439
|
-
file2.write_text(content)
|
|
440
|
-
|
|
441
|
-
return file1, file2
|
|
442
|
-
|
|
443
|
-
def test_git_availability_identical(self):
|
|
444
|
-
"""Test that both implementations report git availability identically"""
|
|
445
|
-
native_available = self.native_repo.is_git_available()
|
|
446
|
-
dulwich_available = self.dulwich_repo.is_git_available()
|
|
447
|
-
|
|
448
|
-
self.assertEqual(
|
|
449
|
-
native_available,
|
|
450
|
-
dulwich_available,
|
|
451
|
-
"Git availability detection differs between implementations",
|
|
452
|
-
)
|
|
453
|
-
self.assertIsInstance(native_available, bool)
|
|
454
|
-
self.assertIsInstance(dulwich_available, bool)
|
|
455
|
-
|
|
456
|
-
def test_repository_initialization_identical(self):
|
|
457
|
-
"""Test that both implementations initialize repositories identically"""
|
|
458
|
-
# Create test files before initialization to test that init adds and commits them
|
|
459
|
-
self._create_identical_file("test_file.txt", "test content for init")
|
|
460
|
-
self._create_identical_file("another_file.py", "print('hello from init')")
|
|
461
|
-
|
|
462
|
-
# Initialize repositories
|
|
463
|
-
native_init = self.native_repo.init_repository()
|
|
464
|
-
dulwich_init = self.dulwich_repo.init_repository()
|
|
465
|
-
|
|
466
|
-
self.assertEqual(
|
|
467
|
-
native_init, dulwich_init, "Repository initialization behavior differs"
|
|
468
|
-
)
|
|
469
|
-
self.assertTrue(native_init, "Native repo initialization should succeed")
|
|
470
|
-
self.assertTrue(dulwich_init, "Dulwich repo initialization should succeed")
|
|
471
|
-
|
|
472
|
-
# Both implementations should create repos
|
|
473
|
-
self.assertTrue(
|
|
474
|
-
self.native_repo.is_git_repository(), "Native should create git repo"
|
|
475
|
-
)
|
|
476
|
-
self.assertTrue(
|
|
477
|
-
self.dulwich_repo.is_git_repository(), "Dulwich should create git repo"
|
|
478
|
-
)
|
|
479
|
-
|
|
480
|
-
# Both should have no uncommitted changes (because init should add and commit all files)
|
|
481
|
-
native_uncommitted = self.native_repo.has_uncommitted_changes()
|
|
482
|
-
dulwich_uncommitted = self.dulwich_repo.has_uncommitted_changes()
|
|
483
|
-
|
|
484
|
-
self.assertEqual(
|
|
485
|
-
native_uncommitted,
|
|
486
|
-
dulwich_uncommitted,
|
|
487
|
-
f"Uncommitted changes after init differs: Native={native_uncommitted}, Dulwich={dulwich_uncommitted}",
|
|
488
|
-
)
|
|
489
|
-
self.assertFalse(
|
|
490
|
-
native_uncommitted, "Native: should have no uncommitted changes after init"
|
|
491
|
-
)
|
|
492
|
-
self.assertFalse(
|
|
493
|
-
dulwich_uncommitted,
|
|
494
|
-
"Dulwich: should have no uncommitted changes after init",
|
|
495
|
-
)
|
|
496
|
-
|
|
497
|
-
# Both should have an initial commit
|
|
498
|
-
native_last_commit = self.native_repo.get_last_commit()
|
|
499
|
-
dulwich_last_commit = self.dulwich_repo.get_last_commit()
|
|
500
|
-
|
|
501
|
-
self.assertIsNotNone(native_last_commit, "Native: should have initial commit")
|
|
502
|
-
self.assertIsNotNone(dulwich_last_commit, "Dulwich: should have initial commit")
|
|
503
|
-
|
|
504
|
-
assert native_last_commit is not None
|
|
505
|
-
assert dulwich_last_commit is not None
|
|
506
|
-
|
|
507
|
-
# Both should have same commit message
|
|
508
|
-
self.assertEqual(
|
|
509
|
-
native_last_commit.message,
|
|
510
|
-
dulwich_last_commit.message,
|
|
511
|
-
"Initial commit messages should be identical",
|
|
512
|
-
)
|
|
513
|
-
self.assertEqual(
|
|
514
|
-
native_last_commit.message,
|
|
515
|
-
"First commit",
|
|
516
|
-
"Initial commit message should be 'First commit'",
|
|
517
|
-
)
|
|
518
|
-
|
|
519
|
-
def test_repository_detection_identical(self):
|
|
520
|
-
"""Test that both implementations detect repositories identically"""
|
|
521
|
-
# Test on non-repo directories
|
|
522
|
-
native_is_repo_before = self.native_repo.is_git_repository()
|
|
523
|
-
dulwich_is_repo_before = self.dulwich_repo.is_git_repository()
|
|
524
|
-
|
|
525
|
-
self.assertEqual(
|
|
526
|
-
native_is_repo_before,
|
|
527
|
-
dulwich_is_repo_before,
|
|
528
|
-
"Repository detection differs on non-repo directories",
|
|
529
|
-
)
|
|
530
|
-
|
|
531
|
-
# Initialize repositories
|
|
532
|
-
self.native_repo.init_repository()
|
|
533
|
-
self.dulwich_repo.init_repository()
|
|
534
|
-
|
|
535
|
-
# Test on repo directories
|
|
536
|
-
native_is_repo_after = self.native_repo.is_git_repository()
|
|
537
|
-
dulwich_is_repo_after = self.dulwich_repo.is_git_repository()
|
|
538
|
-
|
|
539
|
-
self.assertEqual(
|
|
540
|
-
native_is_repo_after,
|
|
541
|
-
dulwich_is_repo_after,
|
|
542
|
-
"Repository detection differs on repo directories",
|
|
543
|
-
)
|
|
544
|
-
self.assertTrue(native_is_repo_after, "Native should detect repo after init")
|
|
545
|
-
self.assertTrue(dulwich_is_repo_after, "Dulwich should detect repo after init")
|
|
546
|
-
|
|
547
|
-
def test_changed_files_detection_identical(self):
|
|
548
|
-
"""Test that both implementations detect changed files identically"""
|
|
549
|
-
# Initialize repositories
|
|
550
|
-
self.native_repo.init_repository()
|
|
551
|
-
self.dulwich_repo.init_repository()
|
|
552
|
-
|
|
553
|
-
# Create identical test files
|
|
554
|
-
self._create_identical_file("test.txt", "test content")
|
|
555
|
-
self._create_identical_file("subdir/nested.txt", "nested content")
|
|
556
|
-
|
|
557
|
-
# Get changed files
|
|
558
|
-
native_changed = set(self.native_repo.get_changed_files())
|
|
559
|
-
dulwich_changed = set(self.dulwich_repo.get_changed_files())
|
|
560
|
-
|
|
561
|
-
self.assertEqual(
|
|
562
|
-
native_changed,
|
|
563
|
-
dulwich_changed,
|
|
564
|
-
f"Changed files detection differs: Native={native_changed}, Dulwich={dulwich_changed}",
|
|
565
|
-
)
|
|
566
|
-
|
|
567
|
-
# Git reports directories for new directory structures
|
|
568
|
-
expected_files = {"test.txt", "subdir/"}
|
|
569
|
-
self.assertEqual(native_changed, expected_files)
|
|
570
|
-
self.assertEqual(dulwich_changed, expected_files)
|
|
571
|
-
|
|
572
|
-
def test_commit_behavior_identical(self):
|
|
573
|
-
"""Test that both implementations commit changes identically"""
|
|
574
|
-
# Initialize repositories
|
|
575
|
-
self.native_repo.init_repository()
|
|
576
|
-
self.dulwich_repo.init_repository()
|
|
577
|
-
|
|
578
|
-
# Create identical test files
|
|
579
|
-
self._create_identical_file("test.txt", "initial content")
|
|
580
|
-
|
|
581
|
-
# Commit changes
|
|
582
|
-
native_commit_success = self.native_repo.commit_changes("Test commit")
|
|
583
|
-
dulwich_commit_success = self.dulwich_repo.commit_changes("Test commit")
|
|
584
|
-
|
|
585
|
-
self.assertEqual(
|
|
586
|
-
native_commit_success,
|
|
587
|
-
dulwich_commit_success,
|
|
588
|
-
"Commit success behavior differs",
|
|
589
|
-
)
|
|
590
|
-
self.assertTrue(native_commit_success, "Native commit should succeed")
|
|
591
|
-
self.assertTrue(dulwich_commit_success, "Dulwich commit should succeed")
|
|
592
|
-
|
|
593
|
-
# Check last commit
|
|
594
|
-
native_last_commit = self.native_repo.get_last_commit()
|
|
595
|
-
dulwich_last_commit = self.dulwich_repo.get_last_commit()
|
|
596
|
-
|
|
597
|
-
self.assertIsNotNone(native_last_commit, "Native should have last commit")
|
|
598
|
-
self.assertIsNotNone(dulwich_last_commit, "Dulwich should have last commit")
|
|
599
|
-
|
|
600
|
-
assert native_last_commit is not None
|
|
601
|
-
assert dulwich_last_commit is not None
|
|
602
|
-
|
|
603
|
-
self.assertEqual(
|
|
604
|
-
native_last_commit.message,
|
|
605
|
-
dulwich_last_commit.message,
|
|
606
|
-
"Commit messages should be identical",
|
|
607
|
-
)
|
|
608
|
-
self.assertEqual(native_last_commit.message, "Test commit")
|
|
609
|
-
|
|
610
|
-
def test_repository_status_identical(self):
|
|
611
|
-
"""Test that both implementations report repository status identically"""
|
|
612
|
-
# Get status on fresh repositories
|
|
613
|
-
native_status = self.native_repo.get_repository_status()
|
|
614
|
-
dulwich_status = self.dulwich_repo.get_repository_status()
|
|
615
|
-
|
|
616
|
-
# Both should be available after initialization
|
|
617
|
-
self.assertEqual(
|
|
618
|
-
native_status.available,
|
|
619
|
-
dulwich_status.available,
|
|
620
|
-
"Repository status availability differs",
|
|
621
|
-
)
|
|
622
|
-
self.assertTrue(native_status.available, "Native repo should be available")
|
|
623
|
-
self.assertTrue(dulwich_status.available, "Dulwich repo should be available")
|
|
624
|
-
|
|
625
|
-
# Test with changes
|
|
626
|
-
self._create_identical_file("test.txt", "content")
|
|
627
|
-
|
|
628
|
-
native_status_with_changes = self.native_repo.get_repository_status()
|
|
629
|
-
dulwich_status_with_changes = self.dulwich_repo.get_repository_status()
|
|
630
|
-
|
|
631
|
-
self.assertEqual(
|
|
632
|
-
native_status_with_changes.has_changes,
|
|
633
|
-
dulwich_status_with_changes.has_changes,
|
|
634
|
-
"Change detection in status differs",
|
|
635
|
-
)
|
|
636
|
-
self.assertTrue(native_status_with_changes.has_changes)
|
|
637
|
-
self.assertTrue(dulwich_status_with_changes.has_changes)
|
|
638
|
-
|
|
639
|
-
def test_config_operations_identical(self):
|
|
640
|
-
"""Test that both implementations handle configuration identically"""
|
|
641
|
-
# Initialize repositories
|
|
642
|
-
self.native_repo.init_repository()
|
|
643
|
-
self.dulwich_repo.init_repository()
|
|
644
|
-
|
|
645
|
-
# Set configuration
|
|
646
|
-
native_set_success = self.native_repo.set_git_config("user.name", "Test User")
|
|
647
|
-
dulwich_set_success = self.dulwich_repo.set_git_config("user.name", "Test User")
|
|
648
|
-
|
|
649
|
-
self.assertEqual(
|
|
650
|
-
native_set_success, dulwich_set_success, "Config set behavior differs"
|
|
651
|
-
)
|
|
652
|
-
self.assertTrue(native_set_success, "Native config set should succeed")
|
|
653
|
-
self.assertTrue(dulwich_set_success, "Dulwich config set should succeed")
|
|
654
|
-
|
|
655
|
-
# Get configuration
|
|
656
|
-
native_config_value = self.native_repo.get_git_config("user.name")
|
|
657
|
-
dulwich_config_value = self.dulwich_repo.get_git_config("user.name")
|
|
658
|
-
|
|
659
|
-
self.assertEqual(
|
|
660
|
-
native_config_value, dulwich_config_value, "Config get behavior differs"
|
|
661
|
-
)
|
|
662
|
-
self.assertEqual(native_config_value, "Test User")
|
|
663
|
-
self.assertEqual(dulwich_config_value, "Test User")
|
|
664
|
-
|
|
665
|
-
def test_remote_operations_identical(self):
|
|
666
|
-
"""Test that both implementations handle remotes identically"""
|
|
667
|
-
# Initialize repositories
|
|
668
|
-
self.native_repo.init_repository()
|
|
669
|
-
self.dulwich_repo.init_repository()
|
|
670
|
-
|
|
671
|
-
# Initially no remotes
|
|
672
|
-
native_initial_remotes = self.native_repo.get_remotes()
|
|
673
|
-
dulwich_initial_remotes = self.dulwich_repo.get_remotes()
|
|
674
|
-
|
|
675
|
-
self.assertEqual(
|
|
676
|
-
set(native_initial_remotes),
|
|
677
|
-
set(dulwich_initial_remotes),
|
|
678
|
-
"Initial remotes differ",
|
|
679
|
-
)
|
|
680
|
-
self.assertEqual(len(native_initial_remotes), 0)
|
|
681
|
-
self.assertEqual(len(dulwich_initial_remotes), 0)
|
|
682
|
-
|
|
683
|
-
# Add remote
|
|
684
|
-
remote_url = "https://example.com/repo.git"
|
|
685
|
-
native_add_success = self.native_repo.add_remote("origin", remote_url)
|
|
686
|
-
dulwich_add_success = self.dulwich_repo.add_remote("origin", remote_url)
|
|
687
|
-
|
|
688
|
-
self.assertEqual(
|
|
689
|
-
native_add_success, dulwich_add_success, "Add remote behavior differs"
|
|
690
|
-
)
|
|
691
|
-
self.assertTrue(native_add_success, "Native add remote should succeed")
|
|
692
|
-
self.assertTrue(dulwich_add_success, "Dulwich add remote should succeed")
|
|
693
|
-
|
|
694
|
-
# Check remote exists
|
|
695
|
-
native_has_origin = self.native_repo.has_remote("origin")
|
|
696
|
-
dulwich_has_origin = self.dulwich_repo.has_remote("origin")
|
|
697
|
-
|
|
698
|
-
self.assertEqual(
|
|
699
|
-
native_has_origin, dulwich_has_origin, "Remote existence check differs"
|
|
700
|
-
)
|
|
701
|
-
self.assertTrue(native_has_origin, "Native should have origin remote")
|
|
702
|
-
self.assertTrue(dulwich_has_origin, "Dulwich should have origin remote")
|
|
703
|
-
|
|
704
|
-
# Get remotes after adding
|
|
705
|
-
native_remotes_after = set(self.native_repo.get_remotes())
|
|
706
|
-
dulwich_remotes_after = set(self.dulwich_repo.get_remotes())
|
|
707
|
-
|
|
708
|
-
self.assertEqual(
|
|
709
|
-
native_remotes_after,
|
|
710
|
-
dulwich_remotes_after,
|
|
711
|
-
"Remotes list differs after adding",
|
|
712
|
-
)
|
|
713
|
-
self.assertIn("origin", native_remotes_after)
|
|
714
|
-
self.assertIn("origin", dulwich_remotes_after)
|
|
715
|
-
|
|
716
|
-
def test_uncommitted_changes_detection_identical(self):
|
|
717
|
-
"""Test that both implementations detect uncommitted changes identically"""
|
|
718
|
-
# Initialize repositories
|
|
719
|
-
self.native_repo.init_repository()
|
|
720
|
-
self.dulwich_repo.init_repository()
|
|
721
|
-
|
|
722
|
-
# Create and commit initial files
|
|
723
|
-
self._create_identical_file("test.txt", "initial")
|
|
724
|
-
self.native_repo.commit_changes("Initial commit")
|
|
725
|
-
self.dulwich_repo.commit_changes("Initial commit")
|
|
726
|
-
|
|
727
|
-
# Should have no changes after commit
|
|
728
|
-
native_no_changes = self.native_repo.has_uncommitted_changes()
|
|
729
|
-
dulwich_no_changes = self.dulwich_repo.has_uncommitted_changes()
|
|
730
|
-
|
|
731
|
-
self.assertEqual(
|
|
732
|
-
native_no_changes,
|
|
733
|
-
dulwich_no_changes,
|
|
734
|
-
"Uncommitted changes detection differs after commit",
|
|
735
|
-
)
|
|
736
|
-
self.assertFalse(
|
|
737
|
-
native_no_changes, "Native should have no changes after commit"
|
|
738
|
-
)
|
|
739
|
-
self.assertFalse(
|
|
740
|
-
dulwich_no_changes, "Dulwich should have no changes after commit"
|
|
741
|
-
)
|
|
742
|
-
|
|
743
|
-
# Modify files - should have changes
|
|
744
|
-
(self.temp_dir1 / "test.txt").write_text("modified")
|
|
745
|
-
(self.temp_dir2 / "test.txt").write_text("modified")
|
|
746
|
-
|
|
747
|
-
native_has_changes = self.native_repo.has_uncommitted_changes()
|
|
748
|
-
dulwich_has_changes = self.dulwich_repo.has_uncommitted_changes()
|
|
749
|
-
|
|
750
|
-
self.assertEqual(
|
|
751
|
-
native_has_changes,
|
|
752
|
-
dulwich_has_changes,
|
|
753
|
-
"Uncommitted changes detection differs after modification",
|
|
754
|
-
)
|
|
755
|
-
self.assertTrue(native_has_changes, "Native should detect changes")
|
|
756
|
-
self.assertTrue(dulwich_has_changes, "Dulwich should detect changes")
|
|
757
|
-
|
|
758
|
-
def test_branch_operations_identical(self):
|
|
759
|
-
"""Test that both implementations handle branches identically"""
|
|
760
|
-
# Create test files before initialization to ensure commits are made
|
|
761
|
-
self._create_identical_file("test.txt", "test content")
|
|
762
|
-
|
|
763
|
-
# Initialize repositories
|
|
764
|
-
self.native_repo.init_repository()
|
|
765
|
-
self.dulwich_repo.init_repository()
|
|
766
|
-
|
|
767
|
-
# Get current branch
|
|
768
|
-
native_branch = self.native_repo.get_current_branch()
|
|
769
|
-
dulwich_branch = self.dulwich_repo.get_current_branch()
|
|
770
|
-
|
|
771
|
-
# Both should return the same type (str or None)
|
|
772
|
-
self.assertEqual(
|
|
773
|
-
type(native_branch),
|
|
774
|
-
type(dulwich_branch),
|
|
775
|
-
"Current branch return types differ",
|
|
776
|
-
)
|
|
777
|
-
|
|
778
|
-
# Get all branches
|
|
779
|
-
native_branches = self.native_repo.get_all_branches()
|
|
780
|
-
dulwich_branches = self.dulwich_repo.get_all_branches()
|
|
781
|
-
|
|
782
|
-
self.assertEqual(
|
|
783
|
-
type(native_branches),
|
|
784
|
-
type(dulwich_branches),
|
|
785
|
-
"All branches should return lists",
|
|
786
|
-
)
|
|
787
|
-
self.assertIsInstance(native_branches, list)
|
|
788
|
-
self.assertIsInstance(dulwich_branches, list)
|
|
789
|
-
# With files to commit, both should have the same branches
|
|
790
|
-
self.assertEqual(
|
|
791
|
-
set(native_branches),
|
|
792
|
-
set(dulwich_branches),
|
|
793
|
-
"Branch lists should be identical",
|
|
794
|
-
)
|
|
795
|
-
|
|
796
|
-
def test_single_main_branch_only(self):
|
|
797
|
-
"""Test that both implementations create only the main branch during initialization"""
|
|
798
|
-
# Create test files before initialization
|
|
799
|
-
self._create_identical_file("test.txt", "test content")
|
|
800
|
-
|
|
801
|
-
# Initialize repositories
|
|
802
|
-
self.native_repo.init_repository()
|
|
803
|
-
self.dulwich_repo.init_repository()
|
|
804
|
-
|
|
805
|
-
# Get all branches for both implementations
|
|
806
|
-
native_branches = self.native_repo.get_all_branches()
|
|
807
|
-
dulwich_branches = self.dulwich_repo.get_all_branches()
|
|
808
|
-
|
|
809
|
-
# Both should have exactly one branch
|
|
810
|
-
self.assertEqual(
|
|
811
|
-
len(native_branches),
|
|
812
|
-
1,
|
|
813
|
-
f"Native repo should have exactly 1 branch, got {len(native_branches)}: {native_branches}",
|
|
814
|
-
)
|
|
815
|
-
self.assertEqual(
|
|
816
|
-
len(dulwich_branches),
|
|
817
|
-
1,
|
|
818
|
-
f"Dulwich repo should have exactly 1 branch, got {len(dulwich_branches)}: {dulwich_branches}",
|
|
819
|
-
)
|
|
820
|
-
|
|
821
|
-
# Both should have the same single branch
|
|
822
|
-
self.assertEqual(
|
|
823
|
-
native_branches,
|
|
824
|
-
dulwich_branches,
|
|
825
|
-
f"Branch lists should be identical: Native={native_branches}, Dulwich={dulwich_branches}",
|
|
826
|
-
)
|
|
827
|
-
|
|
828
|
-
# That branch should be 'main'
|
|
829
|
-
self.assertEqual(
|
|
830
|
-
native_branches[0],
|
|
831
|
-
"main",
|
|
832
|
-
f"Native repo should create 'main' branch, got '{native_branches[0]}'",
|
|
833
|
-
)
|
|
834
|
-
self.assertEqual(
|
|
835
|
-
dulwich_branches[0],
|
|
836
|
-
"main",
|
|
837
|
-
f"Dulwich repo should create 'main' branch, got '{dulwich_branches[0]}'",
|
|
838
|
-
)
|
|
839
|
-
|
|
840
|
-
# Current branch should also be 'main'
|
|
841
|
-
native_current = self.native_repo.get_current_branch()
|
|
842
|
-
dulwich_current = self.dulwich_repo.get_current_branch()
|
|
843
|
-
|
|
844
|
-
self.assertEqual(
|
|
845
|
-
native_current,
|
|
846
|
-
"main",
|
|
847
|
-
f"Native repo current branch should be 'main', got '{native_current}'",
|
|
848
|
-
)
|
|
849
|
-
self.assertEqual(
|
|
850
|
-
dulwich_current,
|
|
851
|
-
"main",
|
|
852
|
-
f"Dulwich repo current branch should be 'main', got '{dulwich_current}'",
|
|
853
|
-
)
|
|
854
|
-
|
|
855
|
-
# Both should report the same current branch
|
|
856
|
-
self.assertEqual(
|
|
857
|
-
native_current,
|
|
858
|
-
dulwich_current,
|
|
859
|
-
f"Current branch should be identical: Native='{native_current}', Dulwich='{dulwich_current}'",
|
|
860
|
-
)
|
|
861
|
-
|
|
862
|
-
# Verify no 'master' branch exists in either implementation
|
|
863
|
-
self.assertNotIn(
|
|
864
|
-
"master",
|
|
865
|
-
native_branches,
|
|
866
|
-
f"Native repo should not create 'master' branch, branches: {native_branches}",
|
|
867
|
-
)
|
|
868
|
-
self.assertNotIn(
|
|
869
|
-
"master",
|
|
870
|
-
dulwich_branches,
|
|
871
|
-
f"Dulwich repo should not create 'master' branch, branches: {dulwich_branches}",
|
|
872
|
-
)
|
|
873
|
-
|
|
874
|
-
def test_comprehensive_workflow_identical(self):
|
|
875
|
-
"""Test a complete workflow to ensure identical behavior throughout"""
|
|
876
|
-
# Initialize
|
|
877
|
-
self.assertTrue(self.native_repo.init_repository())
|
|
878
|
-
self.assertTrue(self.dulwich_repo.init_repository())
|
|
879
|
-
|
|
880
|
-
# Create files
|
|
881
|
-
self._create_identical_file("file1.txt", "content 1")
|
|
882
|
-
self._create_identical_file("dir/file2.txt", "content 2")
|
|
883
|
-
|
|
884
|
-
# Check changes
|
|
885
|
-
native_changes_1 = set(self.native_repo.get_changed_files())
|
|
886
|
-
dulwich_changes_1 = set(self.dulwich_repo.get_changed_files())
|
|
887
|
-
self.assertEqual(native_changes_1, dulwich_changes_1)
|
|
888
|
-
|
|
889
|
-
# Commit
|
|
890
|
-
self.assertTrue(self.native_repo.commit_changes("First commit"))
|
|
891
|
-
self.assertTrue(self.dulwich_repo.commit_changes("First commit"))
|
|
892
|
-
|
|
893
|
-
# Verify no changes after commit
|
|
894
|
-
self.assertFalse(self.native_repo.has_uncommitted_changes())
|
|
895
|
-
self.assertFalse(self.dulwich_repo.has_uncommitted_changes())
|
|
896
|
-
|
|
897
|
-
# Modify files
|
|
898
|
-
(self.temp_dir1 / "file1.txt").write_text("modified content 1")
|
|
899
|
-
(self.temp_dir2 / "file1.txt").write_text("modified content 1")
|
|
900
|
-
|
|
901
|
-
# Create new files
|
|
902
|
-
self._create_identical_file("new_file.txt", "new content")
|
|
903
|
-
|
|
904
|
-
# Check changes again
|
|
905
|
-
native_changes_2 = set(self.native_repo.get_changed_files())
|
|
906
|
-
dulwich_changes_2 = set(self.dulwich_repo.get_changed_files())
|
|
907
|
-
self.assertEqual(native_changes_2, dulwich_changes_2)
|
|
908
|
-
|
|
909
|
-
# Should detect changes
|
|
910
|
-
self.assertTrue(self.native_repo.has_uncommitted_changes())
|
|
911
|
-
self.assertTrue(self.dulwich_repo.has_uncommitted_changes())
|
|
912
|
-
|
|
913
|
-
# Get status
|
|
914
|
-
native_status = self.native_repo.get_repository_status()
|
|
915
|
-
dulwich_status = self.dulwich_repo.get_repository_status()
|
|
916
|
-
|
|
917
|
-
self.assertEqual(native_status.available, dulwich_status.available)
|
|
918
|
-
self.assertEqual(native_status.has_changes, dulwich_status.has_changes)
|
|
919
|
-
|
|
920
|
-
# Commit again
|
|
921
|
-
self.assertTrue(self.native_repo.commit_changes("Second commit"))
|
|
922
|
-
self.assertTrue(self.dulwich_repo.commit_changes("Second commit"))
|
|
923
|
-
|
|
924
|
-
# Get commit history
|
|
925
|
-
native_history = self.native_repo.get_commit_history(limit=5)
|
|
926
|
-
dulwich_history = self.dulwich_repo.get_commit_history(limit=5)
|
|
927
|
-
|
|
928
|
-
self.assertEqual(len(native_history), len(dulwich_history))
|
|
929
|
-
if native_history and dulwich_history:
|
|
930
|
-
self.assertEqual(native_history[0].message, dulwich_history[0].message)
|
|
931
|
-
|
|
932
|
-
def test_merge_conflict_detection_missing_commit_identical(self):
|
|
933
|
-
"""Test merge conflict detection with non-existent remote commit - should be identical"""
|
|
934
|
-
# Initialize repositories
|
|
935
|
-
self.native_repo.init_repository()
|
|
936
|
-
self.dulwich_repo.init_repository()
|
|
937
|
-
|
|
938
|
-
# Create and commit a file
|
|
939
|
-
self._create_identical_file("test.txt", "content")
|
|
940
|
-
self.native_repo.commit_changes("Test commit")
|
|
941
|
-
self.dulwich_repo.commit_changes("Test commit")
|
|
942
|
-
|
|
943
|
-
# Test with non-existent commit hash
|
|
944
|
-
fake_commit = "ed29b9897832c8cb1f04687ef9f515028d3e96ed"
|
|
945
|
-
|
|
946
|
-
native_conflicts = self.native_repo.check_merge_conflicts(fake_commit)
|
|
947
|
-
dulwich_conflicts = self.dulwich_repo.check_merge_conflicts(fake_commit)
|
|
948
|
-
|
|
949
|
-
self.assertEqual(
|
|
950
|
-
native_conflicts,
|
|
951
|
-
dulwich_conflicts,
|
|
952
|
-
f"Merge conflict detection with missing commit differs: Native={native_conflicts}, Dulwich={dulwich_conflicts}",
|
|
953
|
-
)
|
|
954
|
-
# Should both return True (conflicts) for missing commits
|
|
955
|
-
self.assertTrue(
|
|
956
|
-
native_conflicts, "Native should report conflicts for missing commit"
|
|
957
|
-
)
|
|
958
|
-
self.assertTrue(
|
|
959
|
-
dulwich_conflicts, "Dulwich should report conflicts for missing commit"
|
|
960
|
-
)
|
|
961
|
-
|
|
962
|
-
def test_merge_conflict_detection_same_commit_identical(self):
|
|
963
|
-
"""Test merge conflict detection with same commit - should be identical (no conflicts)"""
|
|
964
|
-
# Initialize repositories
|
|
965
|
-
self.native_repo.init_repository()
|
|
966
|
-
self.dulwich_repo.init_repository()
|
|
967
|
-
|
|
968
|
-
# Create and commit a file
|
|
969
|
-
self._create_identical_file("test.txt", "content")
|
|
970
|
-
self.native_repo.commit_changes("Test commit")
|
|
971
|
-
self.dulwich_repo.commit_changes("Test commit")
|
|
972
|
-
|
|
973
|
-
# Get the commit hash
|
|
974
|
-
native_commit = self.native_repo.get_last_commit()
|
|
975
|
-
dulwich_commit = self.dulwich_repo.get_last_commit()
|
|
976
|
-
|
|
977
|
-
assert native_commit is not None
|
|
978
|
-
assert dulwich_commit is not None
|
|
979
|
-
|
|
980
|
-
# Test merge conflict with same commit
|
|
981
|
-
native_conflicts = self.native_repo.check_merge_conflicts(native_commit.hash)
|
|
982
|
-
dulwich_conflicts = self.dulwich_repo.check_merge_conflicts(dulwich_commit.hash)
|
|
983
|
-
|
|
984
|
-
self.assertEqual(
|
|
985
|
-
native_conflicts,
|
|
986
|
-
dulwich_conflicts,
|
|
987
|
-
f"Merge conflict detection with same commit differs: Native={native_conflicts}, Dulwich={dulwich_conflicts}",
|
|
988
|
-
)
|
|
989
|
-
# Should both return False (no conflicts) for same commit
|
|
990
|
-
self.assertFalse(
|
|
991
|
-
native_conflicts, "Native should report no conflicts for same commit"
|
|
992
|
-
)
|
|
993
|
-
self.assertFalse(
|
|
994
|
-
dulwich_conflicts, "Dulwich should report no conflicts for same commit"
|
|
995
|
-
)
|
|
996
|
-
|
|
997
|
-
def test_merge_conflict_detection_unrelated_histories_identical(self):
|
|
998
|
-
"""Test merge conflict detection with unrelated histories"""
|
|
999
|
-
# Create separate repos to simulate unrelated histories
|
|
1000
|
-
temp_dir3 = Path(tempfile.mkdtemp())
|
|
1001
|
-
temp_dir4 = Path(tempfile.mkdtemp())
|
|
1002
|
-
|
|
1003
|
-
try:
|
|
1004
|
-
repo3 = NativeGitRepository(temp_dir3)
|
|
1005
|
-
repo4 = DulwichGitRepository(temp_dir4)
|
|
1006
|
-
|
|
1007
|
-
# Configure git for both
|
|
1008
|
-
self._setup_repo_wrapper(repo3)
|
|
1009
|
-
self._setup_repo_wrapper(repo4)
|
|
1010
|
-
|
|
1011
|
-
# Initialize first repo
|
|
1012
|
-
self.native_repo.init_repository()
|
|
1013
|
-
self.dulwich_repo.init_repository()
|
|
1014
|
-
|
|
1015
|
-
# Create first commit
|
|
1016
|
-
self._create_identical_file("file1.txt", "content1")
|
|
1017
|
-
self.native_repo.commit_changes("First commit")
|
|
1018
|
-
self.dulwich_repo.commit_changes("First commit")
|
|
1019
|
-
|
|
1020
|
-
# Initialize separate repos with different history
|
|
1021
|
-
repo3.init_repository()
|
|
1022
|
-
repo4.init_repository()
|
|
1023
|
-
|
|
1024
|
-
# Create different first commit in separate repos
|
|
1025
|
-
(temp_dir3 / "file2.txt").write_text("different content")
|
|
1026
|
-
(temp_dir4 / "file2.txt").write_text("different content")
|
|
1027
|
-
repo3.commit_changes("Different first commit")
|
|
1028
|
-
repo4.commit_changes("Different first commit")
|
|
1029
|
-
|
|
1030
|
-
# Get commit from separate repo
|
|
1031
|
-
separate_commit = repo3.get_last_commit()
|
|
1032
|
-
|
|
1033
|
-
assert separate_commit is not None
|
|
1034
|
-
|
|
1035
|
-
# Test conflict detection with unrelated commit
|
|
1036
|
-
# Note: This tests the case where commit exists but has no common ancestor
|
|
1037
|
-
native_conflicts = self.native_repo.check_merge_conflicts(
|
|
1038
|
-
separate_commit.hash
|
|
1039
|
-
)
|
|
1040
|
-
dulwich_conflicts = self.dulwich_repo.check_merge_conflicts(
|
|
1041
|
-
separate_commit.hash
|
|
1042
|
-
)
|
|
1043
|
-
|
|
1044
|
-
self.assertEqual(
|
|
1045
|
-
native_conflicts,
|
|
1046
|
-
dulwich_conflicts,
|
|
1047
|
-
f"Merge conflict detection with unrelated history differs: Native={native_conflicts}, Dulwich={dulwich_conflicts}",
|
|
1048
|
-
)
|
|
1049
|
-
# Should both return True (conflicts) for unrelated histories
|
|
1050
|
-
self.assertTrue(
|
|
1051
|
-
native_conflicts, "Native should report conflicts for unrelated history"
|
|
1052
|
-
)
|
|
1053
|
-
self.assertTrue(
|
|
1054
|
-
dulwich_conflicts,
|
|
1055
|
-
"Dulwich should report conflicts for unrelated history",
|
|
1056
|
-
)
|
|
1057
|
-
|
|
1058
|
-
finally:
|
|
1059
|
-
if temp_dir3.exists():
|
|
1060
|
-
shutil.rmtree(temp_dir3, ignore_errors=True)
|
|
1061
|
-
if temp_dir4.exists():
|
|
1062
|
-
shutil.rmtree(temp_dir4, ignore_errors=True)
|
|
1063
|
-
|
|
1064
|
-
def test_ahead_behind_count_identical(self):
|
|
1065
|
-
"""Test ahead/behind counting behavior is identical"""
|
|
1066
|
-
# Initialize repositories
|
|
1067
|
-
self.native_repo.init_repository()
|
|
1068
|
-
self.dulwich_repo.init_repository()
|
|
1069
|
-
|
|
1070
|
-
# Create identical commit history
|
|
1071
|
-
self._create_identical_file("file1.txt", "content1")
|
|
1072
|
-
self.native_repo.commit_changes("Commit 1")
|
|
1073
|
-
self.dulwich_repo.commit_changes("Commit 1")
|
|
1074
|
-
commit1_native = self.native_repo.get_last_commit()
|
|
1075
|
-
commit1_dulwich = self.dulwich_repo.get_last_commit()
|
|
1076
|
-
|
|
1077
|
-
assert commit1_dulwich is not None
|
|
1078
|
-
assert commit1_native is not None
|
|
1079
|
-
|
|
1080
|
-
self._create_identical_file("file2.txt", "content2")
|
|
1081
|
-
self.native_repo.commit_changes("Commit 2")
|
|
1082
|
-
self.dulwich_repo.commit_changes("Commit 2")
|
|
1083
|
-
commit2_native = self.native_repo.get_last_commit()
|
|
1084
|
-
commit2_dulwich = self.dulwich_repo.get_last_commit()
|
|
1085
|
-
|
|
1086
|
-
assert commit2_dulwich is not None
|
|
1087
|
-
assert commit2_native is not None
|
|
1088
|
-
|
|
1089
|
-
# Test same commit (should be 0,0)
|
|
1090
|
-
native_same = self.native_repo.get_ahead_behind_count(
|
|
1091
|
-
commit1_native.hash, commit1_native.hash
|
|
1092
|
-
)
|
|
1093
|
-
dulwich_same = self.dulwich_repo.get_ahead_behind_count(
|
|
1094
|
-
commit1_dulwich.hash, commit1_dulwich.hash
|
|
1095
|
-
)
|
|
1096
|
-
|
|
1097
|
-
self.assertEqual(
|
|
1098
|
-
native_same, dulwich_same, "Same commit ahead/behind should be identical"
|
|
1099
|
-
)
|
|
1100
|
-
self.assertEqual(native_same, (0, 0), "Same commit should be (0,0)")
|
|
1101
|
-
|
|
1102
|
-
# Test different commits
|
|
1103
|
-
native_diff = self.native_repo.get_ahead_behind_count(
|
|
1104
|
-
commit2_native.hash, commit1_native.hash
|
|
1105
|
-
)
|
|
1106
|
-
dulwich_diff = self.dulwich_repo.get_ahead_behind_count(
|
|
1107
|
-
commit2_dulwich.hash, commit1_dulwich.hash
|
|
1108
|
-
)
|
|
1109
|
-
|
|
1110
|
-
self.assertEqual(
|
|
1111
|
-
native_diff,
|
|
1112
|
-
dulwich_diff,
|
|
1113
|
-
"Different commit ahead/behind should be identical",
|
|
1114
|
-
)
|
|
1115
|
-
|
|
1116
|
-
def test_pull_changes_simulation_identical(self):
|
|
1117
|
-
"""Test simulated pull behavior (without actual remote) is identical"""
|
|
1118
|
-
# Initialize repositories
|
|
1119
|
-
self.native_repo.init_repository()
|
|
1120
|
-
self.dulwich_repo.init_repository()
|
|
1121
|
-
|
|
1122
|
-
# Create initial state
|
|
1123
|
-
self._create_identical_file("test.txt", "initial")
|
|
1124
|
-
self.native_repo.commit_changes("Initial commit")
|
|
1125
|
-
self.dulwich_repo.commit_changes("Initial commit")
|
|
1126
|
-
|
|
1127
|
-
# Add fake remote
|
|
1128
|
-
fake_remote_url = "https://github.com/fake/repo.git"
|
|
1129
|
-
native_add_remote = self.native_repo.add_remote("origin", fake_remote_url)
|
|
1130
|
-
dulwich_add_remote = self.dulwich_repo.add_remote("origin", fake_remote_url)
|
|
1131
|
-
|
|
1132
|
-
self.assertEqual(
|
|
1133
|
-
native_add_remote,
|
|
1134
|
-
dulwich_add_remote,
|
|
1135
|
-
"Add remote should behave identically",
|
|
1136
|
-
)
|
|
1137
|
-
self.assertTrue(native_add_remote, "Should successfully add remote")
|
|
1138
|
-
|
|
1139
|
-
# Test pull behavior with non-existent remote (should both fail identically)
|
|
1140
|
-
native_pull = self.native_repo.pull_changes(conflict_resolution="theirs")
|
|
1141
|
-
dulwich_pull = self.dulwich_repo.pull_changes(conflict_resolution="theirs")
|
|
1142
|
-
|
|
1143
|
-
self.assertEqual(
|
|
1144
|
-
native_pull,
|
|
1145
|
-
dulwich_pull,
|
|
1146
|
-
"Pull behavior with fake remote should be identical",
|
|
1147
|
-
)
|
|
1148
|
-
# Both should fail since remote doesn't exist
|
|
1149
|
-
self.assertFalse(native_pull, "Pull from fake remote should fail")
|
|
1150
|
-
self.assertFalse(dulwich_pull, "Pull from fake remote should fail")
|
|
1151
|
-
|
|
1152
|
-
def test_repository_state_after_operations_identical(self):
|
|
1153
|
-
"""Test that repository state remains identical after various operations"""
|
|
1154
|
-
# Initialize repositories
|
|
1155
|
-
self.native_repo.init_repository()
|
|
1156
|
-
self.dulwich_repo.init_repository()
|
|
1157
|
-
|
|
1158
|
-
# Helper to compare full repository state
|
|
1159
|
-
def compare_repo_states(operation_name):
|
|
1160
|
-
native_status = self.native_repo.get_repository_status()
|
|
1161
|
-
dulwich_status = self.dulwich_repo.get_repository_status()
|
|
1162
|
-
|
|
1163
|
-
self.assertEqual(
|
|
1164
|
-
native_status.available,
|
|
1165
|
-
dulwich_status.available,
|
|
1166
|
-
f"After {operation_name}: availability differs",
|
|
1167
|
-
)
|
|
1168
|
-
self.assertEqual(
|
|
1169
|
-
native_status.has_changes,
|
|
1170
|
-
dulwich_status.has_changes,
|
|
1171
|
-
f"After {operation_name}: has_changes differs",
|
|
1172
|
-
)
|
|
1173
|
-
self.assertEqual(
|
|
1174
|
-
native_status.branch,
|
|
1175
|
-
dulwich_status.branch,
|
|
1176
|
-
f"After {operation_name}: current branch differs",
|
|
1177
|
-
)
|
|
1178
|
-
self.assertEqual(
|
|
1179
|
-
set(native_status.branches),
|
|
1180
|
-
set(dulwich_status.branches),
|
|
1181
|
-
f"After {operation_name}: branch list differs",
|
|
1182
|
-
)
|
|
1183
|
-
|
|
1184
|
-
# Compare changed files
|
|
1185
|
-
native_changed = set(self.native_repo.get_changed_files())
|
|
1186
|
-
dulwich_changed = set(self.dulwich_repo.get_changed_files())
|
|
1187
|
-
self.assertEqual(
|
|
1188
|
-
native_changed,
|
|
1189
|
-
dulwich_changed,
|
|
1190
|
-
f"After {operation_name}: changed files differ",
|
|
1191
|
-
)
|
|
1192
|
-
|
|
1193
|
-
# Test state after initialization
|
|
1194
|
-
compare_repo_states("initialization")
|
|
1195
|
-
|
|
1196
|
-
# Add files and test state
|
|
1197
|
-
self._create_identical_file("test.txt", "content")
|
|
1198
|
-
self._create_identical_file("dir/nested.txt", "nested")
|
|
1199
|
-
compare_repo_states("adding files")
|
|
1200
|
-
|
|
1201
|
-
# Commit and test state
|
|
1202
|
-
self.native_repo.commit_changes("Test commit")
|
|
1203
|
-
self.dulwich_repo.commit_changes("Test commit")
|
|
1204
|
-
compare_repo_states("first commit")
|
|
1205
|
-
|
|
1206
|
-
# Modify files and test state
|
|
1207
|
-
(self.temp_dir1 / "test.txt").write_text("modified")
|
|
1208
|
-
(self.temp_dir2 / "test.txt").write_text("modified")
|
|
1209
|
-
compare_repo_states("modifying files")
|
|
1210
|
-
|
|
1211
|
-
# Add new files and test state
|
|
1212
|
-
self._create_identical_file("new.txt", "new content")
|
|
1213
|
-
compare_repo_states("adding new files")
|
|
1214
|
-
|
|
1215
|
-
# Commit again and test state
|
|
1216
|
-
self.native_repo.commit_changes("Second commit")
|
|
1217
|
-
self.dulwich_repo.commit_changes("Second commit")
|
|
1218
|
-
compare_repo_states("second commit")
|
|
1219
|
-
|
|
1220
|
-
def test_stash_behavior_identical(self):
|
|
1221
|
-
"""Test that stash operations behave identically"""
|
|
1222
|
-
# Initialize repositories
|
|
1223
|
-
self.native_repo.init_repository()
|
|
1224
|
-
self.dulwich_repo.init_repository()
|
|
1225
|
-
|
|
1226
|
-
# Create and commit initial files
|
|
1227
|
-
self._create_identical_file("test.txt", "initial")
|
|
1228
|
-
self.native_repo.commit_changes("Initial commit")
|
|
1229
|
-
self.dulwich_repo.commit_changes("Initial commit")
|
|
1230
|
-
|
|
1231
|
-
# Modify files to create changes to stash
|
|
1232
|
-
(self.temp_dir1 / "test.txt").write_text("modified for stash")
|
|
1233
|
-
(self.temp_dir2 / "test.txt").write_text("modified for stash")
|
|
1234
|
-
|
|
1235
|
-
# Verify we have changes before stash
|
|
1236
|
-
self.assertTrue(self.native_repo.has_uncommitted_changes())
|
|
1237
|
-
self.assertTrue(self.dulwich_repo.has_uncommitted_changes())
|
|
1238
|
-
|
|
1239
|
-
# Stash changes
|
|
1240
|
-
native_stash = self.native_repo.stash_changes("Test stash")
|
|
1241
|
-
dulwich_stash = self.dulwich_repo.stash_changes("Test stash")
|
|
1242
|
-
|
|
1243
|
-
self.assertEqual(
|
|
1244
|
-
native_stash, dulwich_stash, "Stash operation results should be identical"
|
|
1245
|
-
)
|
|
1246
|
-
self.assertTrue(native_stash, "Native stash should succeed")
|
|
1247
|
-
self.assertTrue(dulwich_stash, "Dulwich stash should succeed")
|
|
1248
|
-
|
|
1249
|
-
# Verify state after stash
|
|
1250
|
-
native_changes_after = self.native_repo.has_uncommitted_changes()
|
|
1251
|
-
dulwich_changes_after = self.dulwich_repo.has_uncommitted_changes()
|
|
1252
|
-
|
|
1253
|
-
self.assertEqual(
|
|
1254
|
-
native_changes_after,
|
|
1255
|
-
dulwich_changes_after,
|
|
1256
|
-
"Changes detection after stash should be identical",
|
|
1257
|
-
)
|
|
1258
|
-
self.assertFalse(native_changes_after, "Should have no changes after stash")
|
|
1259
|
-
self.assertFalse(dulwich_changes_after, "Should have no changes after stash")
|
|
1260
|
-
|
|
1261
|
-
# Verify file content after stash
|
|
1262
|
-
native_content = (self.temp_dir1 / "test.txt").read_text()
|
|
1263
|
-
dulwich_content = (self.temp_dir2 / "test.txt").read_text()
|
|
1264
|
-
|
|
1265
|
-
self.assertEqual(
|
|
1266
|
-
native_content,
|
|
1267
|
-
dulwich_content,
|
|
1268
|
-
"File content after stash should be identical",
|
|
1269
|
-
)
|
|
1270
|
-
self.assertEqual(
|
|
1271
|
-
native_content, "initial", "File should be reverted to original content"
|
|
1272
|
-
)
|
|
1273
|
-
|
|
1274
|
-
def test_checkout_commit_behavior_identical(self):
|
|
1275
|
-
"""Test that commit checkout behaves identically"""
|
|
1276
|
-
# Initialize repositories
|
|
1277
|
-
self.native_repo.init_repository()
|
|
1278
|
-
self.dulwich_repo.init_repository()
|
|
1279
|
-
|
|
1280
|
-
# Create commit history
|
|
1281
|
-
self._create_identical_file("test.txt", "version 1")
|
|
1282
|
-
self.native_repo.commit_changes("First commit")
|
|
1283
|
-
self.dulwich_repo.commit_changes("First commit")
|
|
1284
|
-
first_commit_native = self.native_repo.get_last_commit()
|
|
1285
|
-
first_commit_dulwich = self.dulwich_repo.get_last_commit()
|
|
1286
|
-
|
|
1287
|
-
self._create_identical_file("test.txt", "version 2")
|
|
1288
|
-
self.native_repo.commit_changes("Second commit")
|
|
1289
|
-
self.dulwich_repo.commit_changes("Second commit")
|
|
1290
|
-
|
|
1291
|
-
assert first_commit_native is not None
|
|
1292
|
-
assert first_commit_dulwich is not None
|
|
1293
|
-
|
|
1294
|
-
# Checkout first commit
|
|
1295
|
-
native_checkout = self.native_repo.checkout_commit(first_commit_native.hash)
|
|
1296
|
-
dulwich_checkout = self.dulwich_repo.checkout_commit(first_commit_dulwich.hash)
|
|
1297
|
-
|
|
1298
|
-
self.assertEqual(
|
|
1299
|
-
native_checkout, dulwich_checkout, "Checkout results should be identical"
|
|
1300
|
-
)
|
|
1301
|
-
|
|
1302
|
-
if native_checkout: # Only test if checkout succeeded
|
|
1303
|
-
# Verify file content after checkout
|
|
1304
|
-
native_content = (self.temp_dir1 / "test.txt").read_text()
|
|
1305
|
-
dulwich_content = (self.temp_dir2 / "test.txt").read_text()
|
|
1306
|
-
|
|
1307
|
-
self.assertEqual(
|
|
1308
|
-
native_content,
|
|
1309
|
-
dulwich_content,
|
|
1310
|
-
"File content after checkout should be identical",
|
|
1311
|
-
)
|
|
1312
|
-
self.assertEqual(
|
|
1313
|
-
native_content, "version 1", "Should have first version content"
|
|
1314
|
-
)
|
|
1315
|
-
|
|
1316
|
-
def test_merge_conflict_with_actual_changes_identical(self):
|
|
1317
|
-
"""Test merge conflict detection with actual conflicting changes"""
|
|
1318
|
-
# Initialize repositories
|
|
1319
|
-
self.native_repo.init_repository()
|
|
1320
|
-
self.dulwich_repo.init_repository()
|
|
1321
|
-
|
|
1322
|
-
# Create base commit
|
|
1323
|
-
self._create_identical_file("conflict.txt", "base content")
|
|
1324
|
-
self.native_repo.commit_changes("Base commit")
|
|
1325
|
-
self.dulwich_repo.commit_changes("Base commit")
|
|
1326
|
-
base_commit_native = self.native_repo.get_last_commit()
|
|
1327
|
-
base_commit_dulwich = self.dulwich_repo.get_last_commit()
|
|
1328
|
-
|
|
1329
|
-
assert base_commit_native is not None
|
|
1330
|
-
assert base_commit_dulwich is not None
|
|
1331
|
-
|
|
1332
|
-
# Create first branch of changes
|
|
1333
|
-
(self.temp_dir1 / "conflict.txt").write_text("branch 1 content")
|
|
1334
|
-
(self.temp_dir2 / "conflict.txt").write_text("branch 1 content")
|
|
1335
|
-
self.native_repo.commit_changes("Branch 1 changes")
|
|
1336
|
-
self.dulwich_repo.commit_changes("Branch 1 changes")
|
|
1337
|
-
branch1_commit_native = self.native_repo.get_last_commit()
|
|
1338
|
-
branch1_commit_dulwich = self.dulwich_repo.get_last_commit()
|
|
1339
|
-
|
|
1340
|
-
assert branch1_commit_native is not None
|
|
1341
|
-
assert branch1_commit_dulwich is not None
|
|
1342
|
-
|
|
1343
|
-
# Reset to base and create conflicting changes
|
|
1344
|
-
self.native_repo.checkout_commit(base_commit_native.hash)
|
|
1345
|
-
self.dulwich_repo.checkout_commit(base_commit_dulwich.hash)
|
|
1346
|
-
|
|
1347
|
-
(self.temp_dir1 / "conflict.txt").write_text("branch 2 content")
|
|
1348
|
-
(self.temp_dir2 / "conflict.txt").write_text("branch 2 content")
|
|
1349
|
-
self.native_repo.commit_changes("Branch 2 changes")
|
|
1350
|
-
self.dulwich_repo.commit_changes("Branch 2 changes")
|
|
1351
|
-
|
|
1352
|
-
# Test conflict detection between conflicting branches
|
|
1353
|
-
native_conflicts = self.native_repo.check_merge_conflicts(
|
|
1354
|
-
branch1_commit_native.hash
|
|
1355
|
-
)
|
|
1356
|
-
dulwich_conflicts = self.dulwich_repo.check_merge_conflicts(
|
|
1357
|
-
branch1_commit_dulwich.hash
|
|
1358
|
-
)
|
|
1359
|
-
|
|
1360
|
-
self.assertEqual(
|
|
1361
|
-
native_conflicts,
|
|
1362
|
-
dulwich_conflicts,
|
|
1363
|
-
"Conflict detection with actual conflicts should be identical",
|
|
1364
|
-
)
|
|
1365
|
-
|
|
1366
|
-
def test_complex_workflow_with_multiple_commits_identical(self):
|
|
1367
|
-
"""Test complex workflow with multiple commits, modifications, and state changes"""
|
|
1368
|
-
# Initialize repositories
|
|
1369
|
-
self.native_repo.init_repository()
|
|
1370
|
-
self.dulwich_repo.init_repository()
|
|
1371
|
-
|
|
1372
|
-
commits_native = []
|
|
1373
|
-
commits_dulwich = []
|
|
1374
|
-
|
|
1375
|
-
# Create a series of commits with various file operations
|
|
1376
|
-
operations = [
|
|
1377
|
-
(
|
|
1378
|
-
"Create initial files",
|
|
1379
|
-
lambda: [
|
|
1380
|
-
self._create_identical_file("file1.txt", "initial content 1"),
|
|
1381
|
-
self._create_identical_file("dir/file2.txt", "initial content 2"),
|
|
1382
|
-
],
|
|
1383
|
-
),
|
|
1384
|
-
(
|
|
1385
|
-
"Modify existing files",
|
|
1386
|
-
lambda: [
|
|
1387
|
-
(self.temp_dir1 / "file1.txt").write_text("modified content 1"),
|
|
1388
|
-
(self.temp_dir2 / "file1.txt").write_text("modified content 1"),
|
|
1389
|
-
],
|
|
1390
|
-
),
|
|
1391
|
-
(
|
|
1392
|
-
"Add new files",
|
|
1393
|
-
lambda: [
|
|
1394
|
-
self._create_identical_file("file3.txt", "new content 3"),
|
|
1395
|
-
self._create_identical_file(
|
|
1396
|
-
"dir/subdir/file4.txt", "nested content 4"
|
|
1397
|
-
),
|
|
1398
|
-
],
|
|
1399
|
-
),
|
|
1400
|
-
(
|
|
1401
|
-
"Delete and recreate",
|
|
1402
|
-
lambda: [
|
|
1403
|
-
(self.temp_dir1 / "file1.txt").unlink(),
|
|
1404
|
-
(self.temp_dir2 / "file1.txt").unlink(),
|
|
1405
|
-
self._create_identical_file("file1.txt", "recreated content 1"),
|
|
1406
|
-
],
|
|
1407
|
-
),
|
|
1408
|
-
(
|
|
1409
|
-
"Mixed operations",
|
|
1410
|
-
lambda: [
|
|
1411
|
-
(self.temp_dir1 / "dir/file2.txt").write_text("updated content 2"),
|
|
1412
|
-
(self.temp_dir2 / "dir/file2.txt").write_text("updated content 2"),
|
|
1413
|
-
self._create_identical_file("final.txt", "final content"),
|
|
1414
|
-
],
|
|
1415
|
-
),
|
|
1416
|
-
]
|
|
1417
|
-
|
|
1418
|
-
for i, (description, operation) in enumerate(operations):
|
|
1419
|
-
# Perform operation
|
|
1420
|
-
operation()
|
|
1421
|
-
|
|
1422
|
-
# Check repository state before commit
|
|
1423
|
-
native_changed = set(self.native_repo.get_changed_files())
|
|
1424
|
-
dulwich_changed = set(self.dulwich_repo.get_changed_files())
|
|
1425
|
-
self.assertEqual(
|
|
1426
|
-
native_changed,
|
|
1427
|
-
dulwich_changed,
|
|
1428
|
-
f"Step {i} ({description}): Changed files should be identical",
|
|
1429
|
-
)
|
|
1430
|
-
|
|
1431
|
-
native_has_changes = self.native_repo.has_uncommitted_changes()
|
|
1432
|
-
dulwich_has_changes = self.dulwich_repo.has_uncommitted_changes()
|
|
1433
|
-
self.assertEqual(
|
|
1434
|
-
native_has_changes,
|
|
1435
|
-
dulwich_has_changes,
|
|
1436
|
-
f"Step {i} ({description}): Uncommitted changes detection should be identical",
|
|
1437
|
-
)
|
|
1438
|
-
|
|
1439
|
-
# Commit changes
|
|
1440
|
-
commit_msg = f"Commit {i + 1}: {description}"
|
|
1441
|
-
native_commit_success = self.native_repo.commit_changes(commit_msg)
|
|
1442
|
-
dulwich_commit_success = self.dulwich_repo.commit_changes(commit_msg)
|
|
1443
|
-
|
|
1444
|
-
self.assertEqual(
|
|
1445
|
-
native_commit_success,
|
|
1446
|
-
dulwich_commit_success,
|
|
1447
|
-
f"Step {i} ({description}): Commit success should be identical",
|
|
1448
|
-
)
|
|
1449
|
-
self.assertTrue(
|
|
1450
|
-
native_commit_success, f"Step {i}: Native commit should succeed"
|
|
1451
|
-
)
|
|
1452
|
-
|
|
1453
|
-
# Get and verify commits
|
|
1454
|
-
native_commit = self.native_repo.get_last_commit()
|
|
1455
|
-
dulwich_commit = self.dulwich_repo.get_last_commit()
|
|
1456
|
-
|
|
1457
|
-
self.assertIsNotNone(native_commit, f"Step {i}: Native should have commit")
|
|
1458
|
-
self.assertIsNotNone(
|
|
1459
|
-
dulwich_commit, f"Step {i}: Dulwich should have commit"
|
|
1460
|
-
)
|
|
1461
|
-
|
|
1462
|
-
assert native_commit is not None
|
|
1463
|
-
assert dulwich_commit is not None
|
|
1464
|
-
|
|
1465
|
-
self.assertEqual(
|
|
1466
|
-
native_commit.message,
|
|
1467
|
-
dulwich_commit.message,
|
|
1468
|
-
f"Step {i}: Commit messages should be identical",
|
|
1469
|
-
)
|
|
1470
|
-
|
|
1471
|
-
commits_native.append(native_commit)
|
|
1472
|
-
commits_dulwich.append(dulwich_commit)
|
|
1473
|
-
|
|
1474
|
-
# Verify no uncommitted changes after commit
|
|
1475
|
-
native_clean = self.native_repo.has_uncommitted_changes()
|
|
1476
|
-
dulwich_clean = self.dulwich_repo.has_uncommitted_changes()
|
|
1477
|
-
self.assertEqual(
|
|
1478
|
-
native_clean,
|
|
1479
|
-
dulwich_clean,
|
|
1480
|
-
f"Step {i}: Post-commit clean state should be identical",
|
|
1481
|
-
)
|
|
1482
|
-
self.assertFalse(native_clean, f"Step {i}: Should be clean after commit")
|
|
1483
|
-
|
|
1484
|
-
# Test commit history
|
|
1485
|
-
native_history = self.native_repo.get_commit_history(limit=10)
|
|
1486
|
-
dulwich_history = self.dulwich_repo.get_commit_history(limit=10)
|
|
1487
|
-
|
|
1488
|
-
self.assertEqual(
|
|
1489
|
-
len(native_history),
|
|
1490
|
-
len(dulwich_history),
|
|
1491
|
-
"Commit history length should be identical",
|
|
1492
|
-
)
|
|
1493
|
-
|
|
1494
|
-
for i, (native_h, dulwich_h) in enumerate(zip(native_history, dulwich_history)):
|
|
1495
|
-
self.assertEqual(
|
|
1496
|
-
native_h.message,
|
|
1497
|
-
dulwich_h.message,
|
|
1498
|
-
f"History item {i}: Commit messages should be identical",
|
|
1499
|
-
)
|
|
1500
|
-
|
|
1501
|
-
# Test ahead/behind counts between different commits
|
|
1502
|
-
if len(commits_native) >= 2:
|
|
1503
|
-
native_ahead_behind = self.native_repo.get_ahead_behind_count(
|
|
1504
|
-
commits_native[-1].hash, commits_native[0].hash
|
|
1505
|
-
)
|
|
1506
|
-
dulwich_ahead_behind = self.dulwich_repo.get_ahead_behind_count(
|
|
1507
|
-
commits_dulwich[-1].hash, commits_dulwich[0].hash
|
|
1508
|
-
)
|
|
1509
|
-
self.assertEqual(
|
|
1510
|
-
native_ahead_behind,
|
|
1511
|
-
dulwich_ahead_behind,
|
|
1512
|
-
"Ahead/behind counts should be identical",
|
|
1513
|
-
)
|
|
1514
|
-
|
|
1515
|
-
def test_empty_commit_edge_cases_identical(self):
|
|
1516
|
-
"""Test edge cases with empty commits and repositories"""
|
|
1517
|
-
# Test on completely empty repositories
|
|
1518
|
-
native_status_empty = self.native_repo.get_repository_status()
|
|
1519
|
-
dulwich_status_empty = self.dulwich_repo.get_repository_status()
|
|
1520
|
-
|
|
1521
|
-
self.assertEqual(
|
|
1522
|
-
native_status_empty.available,
|
|
1523
|
-
dulwich_status_empty.available,
|
|
1524
|
-
"Empty repo availability should be identical",
|
|
1525
|
-
)
|
|
1526
|
-
|
|
1527
|
-
# Initialize but don't commit anything yet
|
|
1528
|
-
self.native_repo.init_repository()
|
|
1529
|
-
self.dulwich_repo.init_repository()
|
|
1530
|
-
|
|
1531
|
-
# Both should handle empty state identically
|
|
1532
|
-
native_changes_empty = self.native_repo.get_changed_files()
|
|
1533
|
-
dulwich_changes_empty = self.dulwich_repo.get_changed_files()
|
|
1534
|
-
self.assertEqual(
|
|
1535
|
-
set(native_changes_empty),
|
|
1536
|
-
set(dulwich_changes_empty),
|
|
1537
|
-
"Empty repo changed files should be identical",
|
|
1538
|
-
)
|
|
1539
|
-
|
|
1540
|
-
# Test merge conflict detection on repos without any commits
|
|
1541
|
-
fake_hash = "1234567890abcdef1234567890abcdef12345678"
|
|
1542
|
-
native_conflicts_empty = self.native_repo.check_merge_conflicts(fake_hash)
|
|
1543
|
-
dulwich_conflicts_empty = self.dulwich_repo.check_merge_conflicts(fake_hash)
|
|
1544
|
-
|
|
1545
|
-
self.assertEqual(
|
|
1546
|
-
native_conflicts_empty,
|
|
1547
|
-
dulwich_conflicts_empty,
|
|
1548
|
-
"Empty repo conflict detection should be identical",
|
|
1549
|
-
)
|
|
1550
|
-
|
|
1551
|
-
# Test with None/empty parameters
|
|
1552
|
-
native_conflicts_none = self.native_repo.check_merge_conflicts("")
|
|
1553
|
-
dulwich_conflicts_none = self.dulwich_repo.check_merge_conflicts("")
|
|
1554
|
-
|
|
1555
|
-
self.assertEqual(
|
|
1556
|
-
native_conflicts_none,
|
|
1557
|
-
dulwich_conflicts_none,
|
|
1558
|
-
"Empty string conflict detection should be identical",
|
|
1559
|
-
)
|
|
1560
|
-
self.assertFalse(native_conflicts_none, "Empty string should return False")
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
358
|
if __name__ == "__main__":
|
|
1564
359
|
loader = unittest.TestLoader()
|
|
1565
360
|
suite = unittest.TestSuite()
|
|
1566
361
|
|
|
1567
362
|
suite.addTests(loader.loadTestsFromTestCase(NativeGitRepositoryTest))
|
|
1568
|
-
suite.addTests(loader.loadTestsFromTestCase(DulwichGitRepositoryTest))
|
|
1569
|
-
suite.addTests(loader.loadTestsFromTestCase(GitImplementationComparisonTest))
|
|
1570
363
|
|
|
1571
364
|
runner = unittest.TextTestRunner(verbosity=2)
|
|
1572
365
|
runner.run(suite)
|