abstra 3.23.12__py3-none-any.whl → 3.24.1__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 +16 -5
- {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/METADATA +1 -1
- {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/RECORD +200 -190
- abstra_internals/cloud_api/__init__.py +17 -8
- abstra_internals/consts/filepaths.py +1 -1
- abstra_internals/contracts_generated.py +616 -596
- abstra_internals/controllers/ai.py +89 -1
- abstra_internals/controllers/git.py +307 -0
- abstra_internals/controllers/main.py +10 -6
- abstra_internals/environment.py +6 -0
- abstra_internals/interface/cli/deploy.py +1 -1
- abstra_internals/interface/cli/editor.py +2 -2
- abstra_internals/interface/sdk/ai.py +1 -0
- abstra_internals/repositories/git/__init__.py +25 -0
- abstra_internals/repositories/git/git_test.py +362 -0
- abstra_internals/repositories/git/native.py +578 -0
- abstra_internals/repositories/git/types.py +273 -0
- abstra_internals/repositories/linter/rules/env_in_bundle.py +5 -5
- abstra_internals/repositories/linter/rules/env_in_bundle_test.py +6 -6
- abstra_internals/repositories/linter/rules/venv_in_bundle.py +9 -16
- abstra_internals/server/blueprints/editor.py +4 -0
- abstra_internals/server/routes/git.py +190 -0
- abstra_internals/server/routes/workspace.py +1 -1
- abstra_internals/services/file_watcher.py +32 -13
- abstra_internals/services/fs.py +4 -4
- abstra_internals/services/fs_test.py +4 -6
- abstra_internals/templates/__init__.py +0 -11
- abstra_statics/dist/assets/{AbstraButton.vue_vue_type_script_setup_true_lang.441fcdfd.js → AbstraButton.vue_vue_type_script_setup_true_lang.aefce2d3.js} +2 -2
- abstra_statics/dist/assets/AbstraLogo.vue_vue_type_script_setup_true_lang.28bc9fc9.js +2 -0
- abstra_statics/dist/assets/ApiKeys.3c1e70dc.js +2 -0
- abstra_statics/dist/assets/App.9d8bd2aa.js +2 -0
- abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.a64c7cee.js +2 -0
- abstra_statics/dist/assets/{BaseLayout.c63dfc2d.js → BaseLayout.72a6c8f2.js} +2 -2
- abstra_statics/dist/assets/{Billing.461db3ef.js → Billing.6b07f282.js} +2 -2
- abstra_statics/dist/assets/{Breadcrumb.27110ec4.js → Breadcrumb.5c786c09.js} +2 -2
- abstra_statics/dist/assets/{Builds.4eecd717.js → Builds.d8c5c61b.js} +2 -2
- abstra_statics/dist/assets/{Card.1d1a9fb7.js → Card.fc77085c.js} +2 -2
- abstra_statics/dist/assets/{CircularLoading.fc66331b.js → CircularLoading.998b223a.js} +2 -2
- abstra_statics/dist/assets/{CloseCircleOutlined.0110bbe2.js → CloseCircleOutlined.9ff269cc.js} +2 -2
- abstra_statics/dist/assets/{ConnectorsView.82e74ae4.css → ConnectorsView.33c5380f.css} +1 -1
- abstra_statics/dist/assets/ConnectorsView.e670738b.js +2 -0
- abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.3ca66327.js +2 -0
- abstra_statics/dist/assets/ContentLayout.0db8d7fb.js +2 -0
- abstra_statics/dist/assets/{CrudView.c16e2f81.js → CrudView.cc6aeaf0.js} +2 -2
- abstra_statics/dist/assets/DocsButton.vue_vue_type_script_setup_true_lang.689d8ce7.js +2 -0
- abstra_statics/dist/assets/{EditorLogin.00a3b3d9.js → EditorLogin.691452b4.js} +2 -2
- abstra_statics/dist/assets/{EditorsView.f7b2843c.js → EditorsView.fcdf0186.js} +2 -2
- abstra_statics/dist/assets/EnvVars.5519b4ce.js +2 -0
- abstra_statics/dist/assets/Error.11fd1f21.js +2 -0
- abstra_statics/dist/assets/ExclamationCircleOutlined.d0aa47da.js +2 -0
- abstra_statics/dist/assets/Files.6ea18d46.js +2 -0
- abstra_statics/dist/assets/{Form.8077681f.js → Form.09de384c.js} +2 -2
- abstra_statics/dist/assets/{FormRunner.055e2c45.js → FormRunner.15be6fa0.js} +2 -2
- abstra_statics/dist/assets/{Home.0ef22910.js → Home.782c5702.js} +2 -2
- abstra_statics/dist/assets/Home.7c495aa9.js +2 -0
- abstra_statics/dist/assets/{Live.e1261458.js → Live.48c10605.js} +2 -2
- abstra_statics/dist/assets/LoadingContainer.82ac3d44.js +2 -0
- abstra_statics/dist/assets/LoadingOutlined.66639b08.js +2 -0
- abstra_statics/dist/assets/Login.4a05f5c5.js +2 -0
- abstra_statics/dist/assets/{Login.041361ea.js → Login.4e852955.js} +2 -2
- abstra_statics/dist/assets/{Login.vue_vue_type_script_setup_true_lang.c2eb444c.js → Login.vue_vue_type_script_setup_true_lang.5161f328.js} +2 -2
- abstra_statics/dist/assets/Logo.65e0b37c.js +2 -0
- abstra_statics/dist/assets/{Logs.f76cde12.js → Logs.7d1acf32.js} +2 -2
- abstra_statics/dist/assets/{LogsController.addd81bf.js → LogsController.0eb2eb30.js} +2 -2
- abstra_statics/dist/assets/Main.0313f4fc.js +2 -0
- abstra_statics/dist/assets/{MockForm.c9441864.js → MockForm.0b819a52.js} +2 -2
- abstra_statics/dist/assets/Navbar.ef64aa09.js +2 -0
- abstra_statics/dist/assets/NewEditor.b9c410fe.css +1 -0
- abstra_statics/dist/assets/NewEditor.c928dbe9.js +8 -0
- abstra_statics/dist/assets/OidcLoginCallback.42a7c4f9.js +2 -0
- abstra_statics/dist/assets/OidcLogoutCallback.35931a68.js +2 -0
- abstra_statics/dist/assets/OmniChat.73d9f6bb.js +6 -0
- abstra_statics/dist/assets/OmniChat.a21fec40.css +1 -0
- abstra_statics/dist/assets/{OnboardingView.fbc4b6fe.js → OnboardingView.25042384.js} +2 -2
- abstra_statics/dist/assets/{Organization.bc495099.js → Organization.66f64939.js} +2 -2
- abstra_statics/dist/assets/Organizations.47868beb.js +2 -0
- abstra_statics/dist/assets/{PhArrowCounterClockwise.vue.156bcd89.js → PhArrowCounterClockwise.vue.78877a50.js} +2 -2
- abstra_statics/dist/assets/{PhArrowSquareOut.vue.d0c95a06.js → PhArrowSquareOut.vue.2ddfc219.js} +2 -2
- abstra_statics/dist/assets/{PhBookBookmark.vue.42e49494.js → PhBookBookmark.vue.41108214.js} +2 -2
- abstra_statics/dist/assets/{PhChats.vue.54d692e4.js → PhChats.vue.71e5cb89.js} +2 -2
- abstra_statics/dist/assets/{PhClockCounterClockwise.vue.d47d66ba.js → PhClockCounterClockwise.vue.854c3cb5.js} +2 -2
- abstra_statics/dist/assets/{PhCopy.vue.a0d9b0ec.js → PhCopy.vue.d116ddfb.js} +2 -2
- abstra_statics/dist/assets/{PhCopySimple.vue.43c74ebe.js → PhCopySimple.vue.5d0f839d.js} +2 -2
- abstra_statics/dist/assets/{PhCube.vue.498c014d.js → PhCube.vue.abf4a034.js} +2 -2
- abstra_statics/dist/assets/PhDatabase.vue.a94d95f6.js +2 -0
- abstra_statics/dist/assets/{PhDotsThreeVertical.vue.0ea03d82.js → PhDotsThreeVertical.vue.5e8ae2a9.js} +2 -2
- abstra_statics/dist/assets/{PhDownloadSimple.vue.c92aeaff.js → PhDownloadSimple.vue.e88f64f1.js} +2 -2
- abstra_statics/dist/assets/{PhFolderPlus.vue.0c210f8d.js → PhFolderPlus.vue.21d377a3.js} +2 -2
- abstra_statics/dist/assets/{PhGear.vue.86c3014a.js → PhGear.vue.363dd83c.js} +2 -2
- abstra_statics/dist/assets/{PhKey.vue.72ce23d3.js → PhKey.vue.23f3a465.js} +2 -2
- abstra_statics/dist/assets/{PhPencil.vue.80ed4b2e.js → PhPencil.vue.feb383e2.js} +2 -2
- abstra_statics/dist/assets/{PhPencilSimple.vue.0046d784.js → PhPencilSimple.vue.ec0eebb4.js} +2 -2
- abstra_statics/dist/assets/{PhRocket.vue.f3302a7e.js → PhRocket.vue.261a42b2.js} +2 -2
- abstra_statics/dist/assets/{PhSignOut.vue.c9150da4.js → PhSignOut.vue.d1d6498f.js} +2 -2
- abstra_statics/dist/assets/{PhSparkle.vue.84ea95fc.js → PhSparkle.vue.b6712d34.js} +2 -2
- abstra_statics/dist/assets/{PhUserList.vue.bce47902.js → PhUserList.vue.e0b8c21b.js} +2 -2
- abstra_statics/dist/assets/{PhUsersThree.vue.0a84dfa4.js → PhUsersThree.vue.8889f957.js} +2 -2
- abstra_statics/dist/assets/PhWarningCircle.vue.2087be7d.js +2 -0
- abstra_statics/dist/assets/{PhWebhooksLogo.vue.a704632d.js → PhWebhooksLogo.vue.d164db1e.js} +2 -2
- abstra_statics/dist/assets/{PlayerConfigProvider.26b585a1.js → PlayerConfigProvider.28e29025.js} +2 -2
- abstra_statics/dist/assets/{PlayerNavbar.0fa6f760.js → PlayerNavbar.aaad1dfd.js} +2 -2
- abstra_statics/dist/assets/Project.2de506d7.js +2 -0
- abstra_statics/dist/assets/{ProjectLogin.934271a6.js → ProjectLogin.22c8b093.js} +2 -2
- abstra_statics/dist/assets/{ProjectSettings.2bf7e6c8.js → ProjectSettings.d065c292.js} +2 -2
- abstra_statics/dist/assets/{ProjectsView.ed31b921.js → ProjectsView.cbd118ac.js} +2 -2
- abstra_statics/dist/assets/{SaveButton.fdf70b31.js → SaveButton.428227de.js} +2 -2
- abstra_statics/dist/assets/ScrollArea.vue_vue_type_script_setup_true_lang.6d724b05.js +2 -0
- abstra_statics/dist/assets/{Sidebar.e69f49bd.css → Sidebar.29baeab0.css} +1 -1
- abstra_statics/dist/assets/{Sidebar.781afa0a.js → Sidebar.41173d8e.js} +2 -2
- abstra_statics/dist/assets/Sql.90e6e2ba.css +1 -0
- abstra_statics/dist/assets/Sql.c070dd2c.js +5 -0
- abstra_statics/dist/assets/Steps.dd51a108.js +2 -0
- abstra_statics/dist/assets/TableCard.529112b9.css +1 -0
- abstra_statics/dist/assets/TableCard.c9a1cf41.js +2 -0
- abstra_statics/dist/assets/TableEditor.1bc47a95.js +2 -0
- abstra_statics/dist/assets/TableEditor.5853a363.css +1 -0
- abstra_statics/dist/assets/Tables.eff119eb.js +2 -0
- abstra_statics/dist/assets/TablesDiagram.a588e7ff.css +1 -0
- abstra_statics/dist/assets/TablesDiagram.d633acaf.js +15 -0
- abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.cf7e34c5.js +2 -0
- abstra_statics/dist/assets/{Tasks.ee450480.js → Tasks.c311b05f.js} +2 -2
- abstra_statics/dist/assets/{UploadOutlined.e3072945.js → UploadOutlined.9aa845de.js} +2 -2
- abstra_statics/dist/assets/View.dd7ba25a.js +2 -0
- abstra_statics/dist/assets/{View.vue_vue_type_script_setup_true_lang.ee5d447b.js → View.vue_vue_type_script_setup_true_lang.e6563207.js} +2 -2
- abstra_statics/dist/assets/{Watermark.891eee9f.js → Watermark.9c9358e3.js} +2 -2
- abstra_statics/dist/assets/{WebEditor.7409cd48.js → WebEditor.83f2a960.js} +2 -2
- abstra_statics/dist/assets/WidgetPreview.7c6a231c.js +2 -0
- abstra_statics/dist/assets/ant-design.42419021.js +2 -0
- abstra_statics/dist/assets/apiKey.403049eb.js +2 -0
- abstra_statics/dist/assets/asyncComputed.47aec2b5.js +2 -0
- abstra_statics/dist/assets/{build.8fa1a961.js → build.45b511b6.js} +2 -2
- abstra_statics/dist/assets/colorHelpers.50ced1e9.js +2 -0
- abstra_statics/dist/assets/console.f0f09e6f.js +17 -0
- abstra_statics/dist/assets/constants.d569f33d.js +2 -0
- abstra_statics/dist/assets/{contracts.generated.c4057ed0.js → contracts.generated.aefe8d0a.js} +2 -2
- abstra_statics/dist/assets/{cssMode.4c65b876.js → cssMode.23271d4a.js} +2 -2
- abstra_statics/dist/assets/{datetime.e5660676.js → datetime.82608dfb.js} +2 -2
- abstra_statics/dist/assets/dayjs.7f71c60a.js +2 -0
- abstra_statics/dist/assets/editor.02184ced.js +2 -0
- abstra_statics/dist/assets/editor.main.0f931e87.js +2 -0
- abstra_statics/dist/assets/fetch.1b3d01a0.js +2 -0
- abstra_statics/dist/assets/files.8b58ee7e.js +2 -0
- abstra_statics/dist/assets/folder.13d3acac.js +2 -0
- abstra_statics/dist/assets/{freemarker2.1d872d48.js → freemarker2.f79b510b.js} +2 -2
- abstra_statics/dist/assets/{handlebars.41fc6db8.js → handlebars.07d5febe.js} +2 -2
- abstra_statics/dist/assets/{html.967e3c6d.js → html.7d6a59b4.js} +3 -3
- abstra_statics/dist/assets/{htmlMode.d38ab72a.js → htmlMode.7779ff94.js} +2 -2
- abstra_statics/dist/assets/{index.8e871bae.js → index.482df04a.js} +2 -2
- abstra_statics/dist/assets/{index.4b93c8ad.js → index.581e2edd.js} +2 -2
- abstra_statics/dist/assets/index.966ac1b9.js +2 -0
- abstra_statics/dist/assets/{index.9021ba5d.js → index.c7a996a6.js} +2 -2
- abstra_statics/dist/assets/{index.03d222dd.js → index.c8a56795.js} +2 -2
- abstra_statics/dist/assets/{index.5f3f38ed.js → index.d31da2c3.js} +2 -2
- abstra_statics/dist/assets/{index.51dbb698.js → index.d53182ed.js} +2 -2
- abstra_statics/dist/assets/{index.b762f5e8.js → index.e71a5f84.js} +2 -2
- abstra_statics/dist/assets/{javascript.0935bea2.js → javascript.4c528c2c.js} +3 -3
- abstra_statics/dist/assets/{jsonMode.2860b71c.js → jsonMode.d6441e9d.js} +2 -2
- abstra_statics/dist/assets/{jwt-decode.esm.7f2ef0df.js → jwt-decode.esm.54a1ea22.js} +8 -8
- abstra_statics/dist/assets/linters.a0f2aa84.js +2 -0
- abstra_statics/dist/assets/{liquid.1bae5f6b.js → liquid.0c441ad2.js} +2 -2
- abstra_statics/dist/assets/member.2260c37e.js +2 -0
- abstra_statics/dist/assets/{metadata.39f9b9ba.js → metadata.0098e20c.js} +2 -2
- abstra_statics/dist/assets/omniChatStore.dd7a1c46.js +8 -0
- abstra_statics/dist/assets/{organization.a877b653.js → organization.668d1b58.js} +2 -2
- abstra_statics/dist/assets/player.4ab4aed5.js +2 -0
- abstra_statics/dist/assets/{plotly.min.d3f75723.js → plotly.min.2a87d7e2.js} +2 -2
- abstra_statics/dist/assets/polling.b5a32c22.js +2 -0
- abstra_statics/dist/assets/{project.d22a89ee.js → project.1b8374f4.js} +2 -2
- abstra_statics/dist/assets/{python.4c1a1300.js → python.7ac27a56.js} +3 -3
- abstra_statics/dist/assets/{razor.ba8bdb33.js → razor.860a0279.js} +2 -2
- abstra_statics/dist/assets/{record.4ffc477c.js → record.e83a2eb2.js} +2 -2
- abstra_statics/dist/assets/{redirect.ce3c0f65.js → redirect.586749f4.js} +2 -2
- abstra_statics/dist/assets/{repository.360feb8f.js → repository.3a331f0f.js} +2 -2
- abstra_statics/dist/assets/{repository.ab3036a9.js → repository.66c7567c.js} +2 -2
- abstra_statics/dist/assets/router.06ee2b9d.js +2 -0
- abstra_statics/dist/assets/router.4dfadf5d.js +18 -0
- abstra_statics/dist/assets/string.61e11a30.js +2 -0
- abstra_statics/dist/assets/{tables.be1c51f8.js → tables.1bcb1140.js} +2 -2
- abstra_statics/dist/assets/{tasksController.bf12e264.js → tasksController.f3adf725.js} +2 -2
- abstra_statics/dist/assets/{toggleHighContrast.c4e1b24d.js → toggleHighContrast.9535bf54.js} +7 -7
- abstra_statics/dist/assets/{tsMode.da264aae.js → tsMode.c0f9fe1a.js} +2 -2
- abstra_statics/dist/assets/{typescript.db5d7517.js → typescript.310eae6d.js} +3 -3
- abstra_statics/dist/assets/url.f5664225.js +2 -0
- abstra_statics/dist/assets/{useCodebaseEvents.42573b00.js → useCodebaseEvents.276cc8f0.js} +2 -2
- abstra_statics/dist/assets/useTables.18fc3efd.js +2 -0
- abstra_statics/dist/assets/userStore.6ab1e5ac.js +2 -0
- abstra_statics/dist/assets/uuid.5b8ba8af.js +2 -0
- abstra_statics/dist/assets/vue-flow-background.af096866.js +2 -0
- abstra_statics/dist/assets/vue-flow-core.6cb99d32.js +22 -0
- abstra_statics/dist/assets/{vue-quill.esm-bundler.37119951.js → vue-quill.esm-bundler.e3d34d0e.js} +2 -2
- abstra_statics/dist/assets/{workspaceStore.50ef2df1.js → workspaceStore.fac1e9a9.js} +2 -2
- abstra_statics/dist/assets/{xml.94b88503.js → xml.04864db4.js} +3 -3
- abstra_statics/dist/assets/{yaml.73b7d5ce.js → yaml.f30375fe.js} +3 -3
- abstra_statics/dist/console.html +14 -15
- abstra_statics/dist/editor.html +13 -13
- abstra_statics/dist/player.html +9 -9
- tests/e2e/test_crud_files.py +1 -0
- abstra_internals/templates/abstraignore +0 -8
- abstra_statics/dist/assets/AbstraLogo.vue_vue_type_script_setup_true_lang.3f03a3ef.js +0 -2
- abstra_statics/dist/assets/ApiKeys.cb561e62.js +0 -2
- abstra_statics/dist/assets/App.dc82115f.js +0 -2
- abstra_statics/dist/assets/App.vue_vue_type_style_index_0_lang.3640ec1c.js +0 -2
- abstra_statics/dist/assets/ConnectorsView.b428e487.js +0 -2
- abstra_statics/dist/assets/ConsoleOmniChat.vue_vue_type_script_setup_true_lang.506f28c6.js +0 -2
- abstra_statics/dist/assets/ContentLayout.228d2328.js +0 -2
- abstra_statics/dist/assets/DocsButton.vue_vue_type_script_setup_true_lang.61381525.js +0 -2
- abstra_statics/dist/assets/EnvVars.242b97c2.js +0 -2
- abstra_statics/dist/assets/Error.466dbb94.js +0 -2
- abstra_statics/dist/assets/ExclamationCircleOutlined.6d10f60b.js +0 -2
- abstra_statics/dist/assets/Files.104385dd.js +0 -2
- abstra_statics/dist/assets/Home.80c7e349.js +0 -2
- abstra_statics/dist/assets/LoadingContainer.6e2b63e4.js +0 -2
- abstra_statics/dist/assets/LoadingOutlined.cd84d9c9.js +0 -2
- abstra_statics/dist/assets/Login.409f4a11.js +0 -2
- abstra_statics/dist/assets/Logo.2de02c4a.js +0 -2
- abstra_statics/dist/assets/Main.4370ed68.js +0 -2
- abstra_statics/dist/assets/Navbar.07ba9452.js +0 -2
- abstra_statics/dist/assets/NewEditor.769f4459.js +0 -8
- abstra_statics/dist/assets/NewEditor.d6e41a05.css +0 -1
- abstra_statics/dist/assets/OidcLoginCallback.a89857fe.js +0 -2
- abstra_statics/dist/assets/OidcLogoutCallback.d151c695.js +0 -2
- abstra_statics/dist/assets/OmniChat.0f64dfec.css +0 -1
- abstra_statics/dist/assets/OmniChat.d015bfa8.js +0 -6
- abstra_statics/dist/assets/Organizations.b630803f.js +0 -2
- abstra_statics/dist/assets/PhPencilSimpleLine.vue.34633dfa.js +0 -2
- abstra_statics/dist/assets/Project.c03610d3.js +0 -2
- abstra_statics/dist/assets/ScrollArea.vue_vue_type_script_setup_true_lang.3bbea426.js +0 -2
- abstra_statics/dist/assets/Sql.3cdc910a.css +0 -1
- abstra_statics/dist/assets/Sql.b6aa38ca.js +0 -5
- abstra_statics/dist/assets/Steps.7c7e4a4a.js +0 -2
- abstra_statics/dist/assets/TableEditor.1e680eaf.css +0 -1
- abstra_statics/dist/assets/TableEditor.dc1b4a2d.js +0 -2
- abstra_statics/dist/assets/Tables.de30953b.js +0 -2
- abstra_statics/dist/assets/TablesDiagram.1ec45dd9.css +0 -1
- abstra_statics/dist/assets/TablesDiagram.97d6a43f.js +0 -15
- abstra_statics/dist/assets/TablesTabs.vue_vue_type_script_setup_true_lang.63aa07d0.js +0 -2
- abstra_statics/dist/assets/View.617ad8d8.js +0 -2
- abstra_statics/dist/assets/WidgetPreview.99f14714.js +0 -2
- abstra_statics/dist/assets/ant-design.4952c8fb.js +0 -2
- abstra_statics/dist/assets/apiKey.864dc66b.js +0 -2
- abstra_statics/dist/assets/asyncComputed.25309626.js +0 -2
- abstra_statics/dist/assets/colorHelpers.71d6d61d.js +0 -2
- abstra_statics/dist/assets/console.3d4702c3.js +0 -25
- abstra_statics/dist/assets/constants.56e8988f.js +0 -2
- abstra_statics/dist/assets/dayjs.c54f8edb.js +0 -2
- abstra_statics/dist/assets/editor.6d0baf6f.js +0 -2
- abstra_statics/dist/assets/editor.main.65812c73.js +0 -2
- abstra_statics/dist/assets/fetch.5136a62d.js +0 -2
- abstra_statics/dist/assets/folder.d7d65e5b.js +0 -2
- abstra_statics/dist/assets/index.23283fbb.js +0 -2
- abstra_statics/dist/assets/index.58e29274.js +0 -2
- abstra_statics/dist/assets/linters.640d6098.js +0 -2
- abstra_statics/dist/assets/member.b7ac8000.js +0 -2
- abstra_statics/dist/assets/omniChatStore.3431c026.js +0 -8
- abstra_statics/dist/assets/player.30593e18.js +0 -2
- abstra_statics/dist/assets/polling.d1c934c7.js +0 -2
- abstra_statics/dist/assets/router.7f571832.js +0 -2
- abstra_statics/dist/assets/router.8fd5b2ad.js +0 -10
- abstra_statics/dist/assets/string.2ed1cde3.js +0 -2
- abstra_statics/dist/assets/url.8583a595.js +0 -2
- abstra_statics/dist/assets/userStore.73b89fbb.js +0 -2
- abstra_statics/dist/assets/uuid.dadede91.js +0 -2
- abstra_statics/dist/assets/vue-flow-background.d2772d9a.js +0 -22
- {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/WHEEL +0 -0
- {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/entry_points.txt +0 -0
- {abstra-3.23.12.dist-info → abstra-3.24.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
import tempfile
|
|
3
|
+
import unittest
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from abstra_internals.repositories.git.native import NativeGitRepository
|
|
7
|
+
from abstra_internals.repositories.git.types import (
|
|
8
|
+
GitStatus,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NativeGitRepositoryTest(unittest.TestCase):
|
|
13
|
+
"""Test suite for NativeGitRepository"""
|
|
14
|
+
|
|
15
|
+
def setUp(self):
|
|
16
|
+
"""Set up test environment"""
|
|
17
|
+
super().setUp()
|
|
18
|
+
self.temp_dir = Path(tempfile.mkdtemp())
|
|
19
|
+
self.repo = NativeGitRepository(self.temp_dir)
|
|
20
|
+
self._original_commit_changes = self.repo.commit_changes
|
|
21
|
+
self.repo.commit_changes = self._commit_changes_wrapper
|
|
22
|
+
|
|
23
|
+
def _commit_changes_wrapper(self, message: str, add_all: bool = True) -> bool:
|
|
24
|
+
"""Wrapper for commit_changes that ensures git is configured"""
|
|
25
|
+
self.ensure_git_configured()
|
|
26
|
+
return self._original_commit_changes(message, add_all)
|
|
27
|
+
|
|
28
|
+
def tearDown(self):
|
|
29
|
+
"""Clean up test environment"""
|
|
30
|
+
super().tearDown()
|
|
31
|
+
if self.temp_dir and self.temp_dir.exists():
|
|
32
|
+
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
|
33
|
+
|
|
34
|
+
def ensure_git_configured(self):
|
|
35
|
+
"""Ensure git is configured for commits (required in CI environments)"""
|
|
36
|
+
if self.repo.is_git_repository() and self.repo.is_git_available():
|
|
37
|
+
if not self.repo.get_git_config("user.name"):
|
|
38
|
+
self.repo.set_git_config("user.name", "Test User")
|
|
39
|
+
if not self.repo.get_git_config("user.email"):
|
|
40
|
+
self.repo.set_git_config("user.email", "test@example.com")
|
|
41
|
+
|
|
42
|
+
def create_test_file(self, filename: str, content: str = "test content"):
|
|
43
|
+
"""Create a test file in the repository"""
|
|
44
|
+
file_path = self.temp_dir / filename
|
|
45
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
46
|
+
file_path.write_text(content)
|
|
47
|
+
return file_path
|
|
48
|
+
|
|
49
|
+
def modify_test_file(self, filename: str, content: str):
|
|
50
|
+
"""Modify an existing test file"""
|
|
51
|
+
file_path = self.temp_dir / filename
|
|
52
|
+
file_path.write_text(content)
|
|
53
|
+
return file_path
|
|
54
|
+
|
|
55
|
+
# Test Methods
|
|
56
|
+
|
|
57
|
+
def test_is_git_available(self):
|
|
58
|
+
"""Test git availability check"""
|
|
59
|
+
result = self.repo.is_git_available()
|
|
60
|
+
self.assertIsInstance(result, bool)
|
|
61
|
+
|
|
62
|
+
def test_init_repository(self):
|
|
63
|
+
"""Test repository initialization"""
|
|
64
|
+
result = self.repo.init_repository()
|
|
65
|
+
self.assertIsInstance(result, bool)
|
|
66
|
+
|
|
67
|
+
def test_is_git_repository_false(self):
|
|
68
|
+
"""Test git repository detection on non-repo"""
|
|
69
|
+
result = self.repo.is_git_repository()
|
|
70
|
+
self.assertFalse(result)
|
|
71
|
+
|
|
72
|
+
def test_is_git_repository_true(self):
|
|
73
|
+
"""Test git repository detection on repo"""
|
|
74
|
+
self.repo.init_repository()
|
|
75
|
+
result = self.repo.is_git_repository()
|
|
76
|
+
self.assertTrue(result)
|
|
77
|
+
|
|
78
|
+
def test_find_git_root(self):
|
|
79
|
+
"""Test finding git root directory"""
|
|
80
|
+
self.repo.init_repository()
|
|
81
|
+
# Create subdirectory and test from there
|
|
82
|
+
sub_dir = self.temp_dir / "subdir"
|
|
83
|
+
sub_dir.mkdir()
|
|
84
|
+
sub_repo = NativeGitRepository(sub_dir)
|
|
85
|
+
root = sub_repo.find_git_root()
|
|
86
|
+
if root:
|
|
87
|
+
# Resolve both paths to handle macOS symlinks (e.g., /var vs /private/var)
|
|
88
|
+
self.assertEqual(root.resolve(), self.temp_dir.resolve())
|
|
89
|
+
|
|
90
|
+
def test_get_current_branch_new_repo(self):
|
|
91
|
+
"""Test getting current branch in new repo"""
|
|
92
|
+
self.repo.init_repository()
|
|
93
|
+
branch = self.repo.get_current_branch()
|
|
94
|
+
self.assertIsInstance(branch, (str, type(None)))
|
|
95
|
+
|
|
96
|
+
def test_get_all_branches_empty(self):
|
|
97
|
+
"""Test getting all branches in empty repo"""
|
|
98
|
+
self.repo.init_repository()
|
|
99
|
+
branches = self.repo.get_all_branches()
|
|
100
|
+
self.assertIsInstance(branches, list)
|
|
101
|
+
|
|
102
|
+
def test_commit_and_get_last_commit(self):
|
|
103
|
+
"""Test committing and getting last commit"""
|
|
104
|
+
self.repo.init_repository()
|
|
105
|
+
self.create_test_file("test.txt", "initial content")
|
|
106
|
+
|
|
107
|
+
# Commit changes
|
|
108
|
+
success = self.repo.commit_changes("Test commit")
|
|
109
|
+
self.assertTrue(success)
|
|
110
|
+
|
|
111
|
+
# Get last commit
|
|
112
|
+
last_commit = self.repo.get_last_commit()
|
|
113
|
+
self.assertIsNotNone(last_commit)
|
|
114
|
+
|
|
115
|
+
assert last_commit is not None
|
|
116
|
+
|
|
117
|
+
self.assertEqual(last_commit.message, "Test commit")
|
|
118
|
+
|
|
119
|
+
def test_get_commit_history(self):
|
|
120
|
+
"""Test getting commit history"""
|
|
121
|
+
self.repo.init_repository()
|
|
122
|
+
|
|
123
|
+
# Create multiple commits
|
|
124
|
+
for i in range(3):
|
|
125
|
+
self.create_test_file(f"test{i}.txt", f"content {i}")
|
|
126
|
+
self.repo.commit_changes(f"Commit {i}")
|
|
127
|
+
|
|
128
|
+
history = self.repo.get_commit_history(limit=2)
|
|
129
|
+
self.assertIsInstance(history, list)
|
|
130
|
+
self.assertLessEqual(len(history), 2)
|
|
131
|
+
if history:
|
|
132
|
+
self.assertEqual(history[0].message, "Commit 2")
|
|
133
|
+
|
|
134
|
+
def test_get_changed_files(self):
|
|
135
|
+
"""Test getting changed files"""
|
|
136
|
+
self.repo.init_repository()
|
|
137
|
+
|
|
138
|
+
# Create and commit initial file
|
|
139
|
+
self.create_test_file("test.txt", "initial")
|
|
140
|
+
self.repo.commit_changes("Initial commit")
|
|
141
|
+
|
|
142
|
+
# Modify file
|
|
143
|
+
self.modify_test_file("test.txt", "modified")
|
|
144
|
+
|
|
145
|
+
# Create new file
|
|
146
|
+
self.create_test_file("new.txt", "new content")
|
|
147
|
+
|
|
148
|
+
changed_files = self.repo.get_changed_files()
|
|
149
|
+
self.assertIsInstance(changed_files, list)
|
|
150
|
+
self.assertIn("test.txt", changed_files)
|
|
151
|
+
self.assertIn("new.txt", changed_files)
|
|
152
|
+
|
|
153
|
+
def test_get_changed_files_with_status(self):
|
|
154
|
+
"""Test getting changed files with status"""
|
|
155
|
+
self.repo.init_repository()
|
|
156
|
+
|
|
157
|
+
# Create and commit initial file
|
|
158
|
+
self.create_test_file("test.txt", "initial")
|
|
159
|
+
self.repo.commit_changes("Initial commit")
|
|
160
|
+
|
|
161
|
+
# Modify file
|
|
162
|
+
self.modify_test_file("test.txt", "modified")
|
|
163
|
+
|
|
164
|
+
# Create new file
|
|
165
|
+
self.create_test_file("new.txt", "new content")
|
|
166
|
+
|
|
167
|
+
changed_files = self.repo.get_changed_files_with_status()
|
|
168
|
+
self.assertIsInstance(changed_files, list)
|
|
169
|
+
|
|
170
|
+
file_paths = [f.path for f in changed_files]
|
|
171
|
+
self.assertIn("test.txt", file_paths)
|
|
172
|
+
self.assertIn("new.txt", file_paths)
|
|
173
|
+
|
|
174
|
+
def test_has_uncommitted_changes(self):
|
|
175
|
+
"""Test checking for uncommitted changes"""
|
|
176
|
+
self.repo.init_repository()
|
|
177
|
+
|
|
178
|
+
# Initially should have no changes after init with first commit
|
|
179
|
+
initial_changes = self.repo.has_uncommitted_changes()
|
|
180
|
+
self.assertFalse(initial_changes)
|
|
181
|
+
|
|
182
|
+
# Create file - should have changes
|
|
183
|
+
self.create_test_file("test.txt", "content")
|
|
184
|
+
after_create = self.repo.has_uncommitted_changes()
|
|
185
|
+
self.assertTrue(after_create)
|
|
186
|
+
|
|
187
|
+
# Commit - should have no changes
|
|
188
|
+
self.repo.commit_changes("Test commit")
|
|
189
|
+
after_commit = self.repo.has_uncommitted_changes()
|
|
190
|
+
self.assertFalse(after_commit)
|
|
191
|
+
|
|
192
|
+
def test_get_repository_status(self):
|
|
193
|
+
"""Test getting comprehensive repository status"""
|
|
194
|
+
status = self.repo.get_repository_status()
|
|
195
|
+
|
|
196
|
+
self.assertIsInstance(status, GitStatus)
|
|
197
|
+
self.assertIsInstance(status.available, bool)
|
|
198
|
+
self.assertIsInstance(status.branches, list)
|
|
199
|
+
self.assertIsInstance(status.has_changes, bool)
|
|
200
|
+
|
|
201
|
+
def test_config_operations(self):
|
|
202
|
+
"""Test git config operations"""
|
|
203
|
+
self.repo.init_repository()
|
|
204
|
+
|
|
205
|
+
# Set config
|
|
206
|
+
set_success = self.repo.set_git_config("user.name", "Test User")
|
|
207
|
+
self.assertTrue(set_success)
|
|
208
|
+
|
|
209
|
+
# Get config
|
|
210
|
+
retrieved_value = self.repo.get_git_config("user.name")
|
|
211
|
+
self.assertEqual(retrieved_value, "Test User")
|
|
212
|
+
|
|
213
|
+
def test_remote_operations(self):
|
|
214
|
+
"""Test remote operations"""
|
|
215
|
+
self.repo.init_repository()
|
|
216
|
+
|
|
217
|
+
# Initially no remotes
|
|
218
|
+
initial_remotes = self.repo.get_remotes()
|
|
219
|
+
self.assertIsInstance(initial_remotes, list)
|
|
220
|
+
|
|
221
|
+
# Add remote
|
|
222
|
+
add_success = self.repo.add_remote("origin", "https://example.com/repo.git")
|
|
223
|
+
self.assertTrue(add_success)
|
|
224
|
+
|
|
225
|
+
# Check remote exists
|
|
226
|
+
has_origin = self.repo.has_remote("origin")
|
|
227
|
+
self.assertTrue(has_origin)
|
|
228
|
+
|
|
229
|
+
# Get remotes after adding
|
|
230
|
+
remotes_after = self.repo.get_remotes()
|
|
231
|
+
self.assertIn("origin", remotes_after)
|
|
232
|
+
|
|
233
|
+
def test_stash_changes(self):
|
|
234
|
+
"""Test stashing changes"""
|
|
235
|
+
self.repo.init_repository()
|
|
236
|
+
|
|
237
|
+
# Create and commit initial file
|
|
238
|
+
self.create_test_file("test.txt", "initial")
|
|
239
|
+
self.repo.commit_changes("Initial commit")
|
|
240
|
+
|
|
241
|
+
# Modify file
|
|
242
|
+
self.modify_test_file("test.txt", "modified")
|
|
243
|
+
|
|
244
|
+
# Check we have changes
|
|
245
|
+
has_changes_before = self.repo.has_uncommitted_changes()
|
|
246
|
+
self.assertTrue(has_changes_before)
|
|
247
|
+
|
|
248
|
+
# Stash changes
|
|
249
|
+
stash_success = self.repo.stash_changes("Test stash")
|
|
250
|
+
self.assertTrue(stash_success)
|
|
251
|
+
|
|
252
|
+
# Check changes after stash
|
|
253
|
+
has_changes_after = self.repo.has_uncommitted_changes()
|
|
254
|
+
self.assertFalse(has_changes_after)
|
|
255
|
+
|
|
256
|
+
def test_checkout_commit(self):
|
|
257
|
+
"""Test checking out specific commit"""
|
|
258
|
+
self.repo.init_repository()
|
|
259
|
+
|
|
260
|
+
# Create commits
|
|
261
|
+
self.create_test_file("test.txt", "version 1")
|
|
262
|
+
self.repo.commit_changes("First commit")
|
|
263
|
+
first_commit = self.repo.get_last_commit()
|
|
264
|
+
|
|
265
|
+
self.modify_test_file("test.txt", "version 2")
|
|
266
|
+
self.repo.commit_changes("Second commit")
|
|
267
|
+
|
|
268
|
+
# Checkout first commit
|
|
269
|
+
self.assertIsNotNone(first_commit)
|
|
270
|
+
|
|
271
|
+
assert first_commit is not None
|
|
272
|
+
|
|
273
|
+
checkout_success = self.repo.checkout_commit(first_commit.hash)
|
|
274
|
+
|
|
275
|
+
if checkout_success:
|
|
276
|
+
# Read file content after checkout
|
|
277
|
+
file_content = (self.temp_dir / "test.txt").read_text()
|
|
278
|
+
self.assertEqual(file_content, "version 1")
|
|
279
|
+
|
|
280
|
+
def test_get_ahead_behind_count(self):
|
|
281
|
+
"""Test calculating ahead/behind counts"""
|
|
282
|
+
self.repo.init_repository()
|
|
283
|
+
|
|
284
|
+
# Create two commits
|
|
285
|
+
self.create_test_file("test1.txt", "content 1")
|
|
286
|
+
self.repo.commit_changes("First commit")
|
|
287
|
+
first_commit = self.repo.get_last_commit()
|
|
288
|
+
|
|
289
|
+
self.create_test_file("test2.txt", "content 2")
|
|
290
|
+
self.repo.commit_changes("Second commit")
|
|
291
|
+
second_commit = self.repo.get_last_commit()
|
|
292
|
+
|
|
293
|
+
self.assertIsNotNone(first_commit)
|
|
294
|
+
self.assertIsNotNone(second_commit)
|
|
295
|
+
|
|
296
|
+
assert first_commit is not None
|
|
297
|
+
assert second_commit is not None
|
|
298
|
+
|
|
299
|
+
# Same commits should be 0,0
|
|
300
|
+
same_counts = self.repo.get_ahead_behind_count(
|
|
301
|
+
first_commit.hash, first_commit.hash
|
|
302
|
+
)
|
|
303
|
+
self.assertEqual(same_counts, (0, 0))
|
|
304
|
+
|
|
305
|
+
# Different commits
|
|
306
|
+
diff_counts = self.repo.get_ahead_behind_count(
|
|
307
|
+
second_commit.hash, first_commit.hash
|
|
308
|
+
)
|
|
309
|
+
self.assertIsInstance(diff_counts, tuple)
|
|
310
|
+
self.assertEqual(len(diff_counts), 2)
|
|
311
|
+
|
|
312
|
+
def test_check_merge_conflicts_simple(self):
|
|
313
|
+
"""Test merge conflict detection (simple case)"""
|
|
314
|
+
self.repo.init_repository()
|
|
315
|
+
|
|
316
|
+
# Create commit
|
|
317
|
+
self.create_test_file("test.txt", "content")
|
|
318
|
+
self.repo.commit_changes("Test commit")
|
|
319
|
+
commit = self.repo.get_last_commit()
|
|
320
|
+
|
|
321
|
+
self.assertIsNotNone(commit)
|
|
322
|
+
|
|
323
|
+
assert commit is not None
|
|
324
|
+
|
|
325
|
+
# Check conflict with same commit (should be false)
|
|
326
|
+
has_conflicts = self.repo.check_merge_conflicts(commit.hash)
|
|
327
|
+
self.assertIsInstance(has_conflicts, bool)
|
|
328
|
+
|
|
329
|
+
def test_revert_commit(self):
|
|
330
|
+
"""Test reverting to previous commit"""
|
|
331
|
+
self.repo.init_repository()
|
|
332
|
+
|
|
333
|
+
# Create first version
|
|
334
|
+
self.create_test_file("test.txt", "version 1")
|
|
335
|
+
self.repo.commit_changes("First commit")
|
|
336
|
+
first_commit = self.repo.get_last_commit()
|
|
337
|
+
|
|
338
|
+
# Create second version
|
|
339
|
+
self.modify_test_file("test.txt", "version 2")
|
|
340
|
+
self.repo.commit_changes("Second commit")
|
|
341
|
+
|
|
342
|
+
# Revert to first commit
|
|
343
|
+
self.assertIsNotNone(first_commit)
|
|
344
|
+
|
|
345
|
+
assert first_commit is not None
|
|
346
|
+
|
|
347
|
+
revert_success = self.repo.revert_commit(first_commit.hash)
|
|
348
|
+
|
|
349
|
+
if revert_success:
|
|
350
|
+
# Check file content
|
|
351
|
+
file_content = (self.temp_dir / "test.txt").read_text()
|
|
352
|
+
self.assertEqual(file_content, "version 1")
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
if __name__ == "__main__":
|
|
356
|
+
loader = unittest.TestLoader()
|
|
357
|
+
suite = unittest.TestSuite()
|
|
358
|
+
|
|
359
|
+
suite.addTests(loader.loadTestsFromTestCase(NativeGitRepositoryTest))
|
|
360
|
+
|
|
361
|
+
runner = unittest.TextTestRunner(verbosity=2)
|
|
362
|
+
runner.run(suite)
|