Skip to content

[IMP] databases: link a repository to a database from the command line - #107

Merged
brinkflew merged 4 commits into
betafrom
avs-command-db
Jul 29, 2026
Merged

[IMP] databases: link a repository to a database from the command line#107
brinkflew merged 4 commits into
betafrom
avs-command-db

Conversation

@brinkflew

@brinkflew brinkflew commented Nov 18, 2025

Copy link
Copy Markdown
Contributor

Description

Adds odev database, a command editing the parameters of a local database without running it —
linked repository, virtual environment, worktree and whitelisting — and gives odev code <database> <repository> the same ability to persist a repository, which is the invocation issue #101 reports.

odev code accepting both a database and a repository has worked since
odev-plugin-editor-base@abd6288 removed the error the issue was filed for. What is still broken is
that the repository applied to that single invocation and was never saved, so the next odev code <database> had lost it again. Persisting it is also what makes the database usable with every
other command relying on that link. The plugin side is
odoo-odev/odev-plugin-editor-base#8 and needs this PR first.

Reworked since the first review

Both callers go through the new LocalDatabase.link_repository, which normalizes its argument
through GitConnector: repository names, HTTPS and SSH URLs and paths to local clones are all
accepted and stored as organization/repository. Storing the raw argument, as the command did,
corrupted the link for anything but a bare name — the stored value is split on its first slash when
read back, so a URL yielded an organization of https:.

  • Values were written with UPDATE ... WHERE name = ..., which matches no row for a database odev
    has never run, so setting a parameter on one silently did nothing while reporting success.
    Setting now goes through the model, whose write is an upsert.
  • Changing the repository left the branch of the previous one attached to the new one. The
    repository setter now clears the cached branch.
  • --set-repo and --remove-repo (and their venv and worktree counterparts) could be passed
    together, in which case the removal silently won. They are now rejected as mutually exclusive.
    Command._exclusive_arguments cannot express this: it requires exactly one argument of the group
    to be present, which makes the group mandatory as well as exclusive, and these are all optional.
  • Called with the database and nothing else, the command did nothing and said nothing. It now
    prints the current parameters — @lse-odoo's review comment, answered without a second command:
    odev database <name> reads, odev database <name> --set-… writes.
  • GitConnector errors surfaced raw instead of going through self.error.

StoreDatabases.set_value is kept, because clearing a value is the one thing that cannot go through
the model: the properties fall back to reading the data store when their cached value is empty, and
would write the cleared value straight back. It now binds its value as a query parameter and checks
the column against the table definition instead of interpolating both into the query — repr()
quotes a string containing a quote with double quotes, which PostgreSQL reads as an identifier.
PostgresDatabase.query grew the params argument it needs to forward for that, which
PostgresConnector.query already accepted.

Two supporting fixes, both needed by the command and both bugs in their own right:

  • GitCommand.worktrees read self.args.version guarded only by the presence of args. A command
    removing that argument has no version attribute at all, so any use of grouped_worktrees raised
    AttributeError.
  • args.Flag dropped the default it was given when passed an explicit action, so the new
    args.FlagOptional could not be given one.

Note for reviewers

args.FlagOptional is a three-state flag: --whitelist sets True, --no-whitelist sets False,
and omitting both leaves the stored value alone. It is documented alongside args.Flag in the
commands tutorial.

Tests live in tests/tests/commands/test_database_command.py: a name, an HTTPS URL and an SSH URL
all store organization/repository; --set-repo on a database with no store row creates it (the
silent-no-op guard); set and remove together are rejected and leave the store untouched; the three
whitelist states; relinking clears a stale branch; and an unknown worktree errors, which is the case
that fails without the GitCommand.worktrees fix. Full test suite passes.

Linked Issues

Compliance

  • I have read the contribution guide
  • I made sure the documentation is up-to-date both in doctrings and the docs directory
  • I have added or modified unit tests where necessary
  • I have added new libraries to the requirements.txt file, if any
  • I have incremented the version number according the versioning guide
  • The PR contains my changes only and no other external commit

🤖 Generated with Claude Code

https://claude.ai/code/session_01K8csZBrrBYp8oqH5paxTAm

@brinkflew brinkflew self-assigned this Nov 18, 2025
@brinkflew brinkflew added the enhancement New feature or request label Nov 18, 2025
@brinkflew
brinkflew requested a review from a team November 18, 2025 17:52

@lse-odoo lse-odoo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

functionallity speacking, would it make sense to also have a command to get the actual current data ? for example giving:
odev database test repository
would give the current directory while:
odev database test repository "lse-odoo/repository"
would set its value

Comment thread odev/commands/database/database.py
@brinkflew

Copy link
Copy Markdown
Contributor Author

functionallity speacking, would it make sense to also have a command to get the actual current data ? for example giving: odev database test repository would give the current directory while: odev database test repository "lse-odoo/repository" would set its value

So more like the odev config command, that could indeed make sense but I'm afraid this would be too much of a duplicate with odev info and odev ls that already prints those. Maybe the best would be to edit odev info so it could set values and not only print them, but some of those won't be editable and I'm not sure how to make that clear a field can or cannot be changed...

Comment thread odev/commands/database/database.py Outdated
@lse-odoo

Copy link
Copy Markdown
Contributor

functionallity speacking, would it make sense to also have a command to get the actual current data ? for example giving: odev database test repository would give the current directory while: odev database test repository "lse-odoo/repository" would set its value

So more like the odev config command, that could indeed make sense but I'm afraid this would be too much of a duplicate with odev info and odev ls that already prints those. Maybe the best would be to edit odev info so it could set values and not only print them, but some of those won't be editable and I'm not sure how to make that clear a field can or cannot be changed...

I feel like it's becoming more and more complicated personally. The more command we add, the more the complexity it gets. The ideas are good in themselves, but I guess it can become complicate for a new comers.
It's arguable if odev ls or having odev database --list would make more sense for instance. odev info can work without having the database locally so is a bit different, but it could be interesting to have kind of like aliases (to avoid dropping "old" commands). For example the odev database --list command mentioned before (that internally would just call odev ls. We could also have odev database blabla.odoo.com --info (or without --info) that would word like odev info but here we knows that the database is locally restored.

I am also wondering if "database" command name should be rather rename "local-database" as here all commands make sense only for database installed locally, it might avoid ambiguity on the scope of the action.

In the long term I feel that having "group" of commands might make sense in odev to avoid having 10 000 commands listed in help and have a better separation of the "category" of commands (even if it would be arguable in which category belongs which command). This would make sense with plugin in my opinion as generally they include commands for a given scope/category. Here for example being in the group "local-database" so that any odev command have to be prefixed with "local-database" before calling the real command "info, list, etc." could make sense

@brinkflew
brinkflew marked this pull request as draft December 22, 2025 08:51
@brinkflew
brinkflew changed the base branch from main to beta December 22, 2025 08:51
Base automatically changed from beta to main January 28, 2026 18:44
Allow change states and parameters of a local database without
running it:

- change or remove linked worktree
- change or remove linked virtual environment
- change or remove linked repository
- (un)whitelist
Reworks the `odev database` command so that it edits databases through the model
rather than writing to the data store directly, and adds the same capability to
`odev code <database> <repository>`, which is the invocation issue #101 reports.

`odev code` accepting both a database and a repository has worked since
odev-plugin-editor-base@abd6288 removed the error the issue was filed for, but the
repository applied to that single invocation and was never saved, so the next
`odev code <database>` had lost it again. It is now persisted, which is also what
makes the database usable with every other command relying on that link.

Both go through the new `LocalDatabase.link_repository`, which normalizes its
argument through `GitConnector`: repository names, HTTPS and SSH URLs and paths to
local clones are all accepted and stored as `organization/repository`. Storing the
raw argument, as the command did, corrupted the link for anything but a bare name:
the stored value is split on its first slash when read back, so a URL yielded an
organization of `https:`.

Other fixes to the command:

- Values were written with `UPDATE ... WHERE name = ...`, which matches no row for
  a database that odev has never run, so setting a parameter on one silently did
  nothing while reporting success. Setting now goes through the model, whose write
  is an upsert.
- Changing the repository left the branch of the previous one attached to the new
  one. The `repository` setter now clears the cached branch.
- `--set-repo` and `--remove-repo` (and their venv and worktree counterparts) could
  be passed together, in which case the removal silently won. They are now rejected
  as mutually exclusive. `Command._exclusive_arguments` cannot express this: it
  requires exactly one argument of the group to be present, making the group
  mandatory as well as exclusive.
- Called with no argument but the database, the command did nothing and said
  nothing; it now prints the current parameters, as asked in review.
- `GitConnector` errors surfaced raw instead of going through `self.error`.

`StoreDatabases.set_value` is kept, since clearing a value is the one thing that
cannot go through the model — the properties fall back to reading the data store
when their cached value is empty, and would write the cleared value straight back.
It now binds its value as a query parameter and checks the column against the table
definition, instead of interpolating both into the query: `repr()` quotes strings
containing a quote with double quotes, which PostgreSQL reads as an identifier.
`PostgresDatabase.query` grew the `params` argument it needs to forward for that,
which `PostgresConnector.query` already accepted.

Two supporting fixes:

- `GitCommand.worktrees` read `self.args.version` guarded only by the presence of
  `args`. A command removing that argument has no `version` attribute at all, so
  any use of `grouped_worktrees` raised `AttributeError`.
- `args.Flag` dropped the default it was given when passed an explicit action, so
  `args.FlagOptional` could not be given one.

Closes #101
`args.FlagOptional` is the argument the `database` command relies on to tell a
value being turned off apart from a value being left alone, and the tutorial only
documented `args.Flag`.

Claude-Session: https://claude.ai/code/session_01K8csZBrrBYp8oqH5paxTAm
@brinkflew brinkflew changed the title [ADD] Database command to change database parameters without starting it [IMP] databases: link a repository to a database from the command line Jul 27, 2026
@brinkflew
brinkflew changed the base branch from main to beta July 27, 2026 00:29
@brinkflew
brinkflew marked this pull request as ready for review July 27, 2026 00:29

@lse-odoo lse-odoo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't tested, but the codes looks perfect to me

@brinkflew
brinkflew merged commit 93d8b12 into beta Jul 29, 2026
6 checks passed
@brinkflew
brinkflew deleted the avs-command-db branch July 29, 2026 11:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Impossible to link database and repository

2 participants