Skip to content

config: unify Get{Source,Store,Destination} behaviour - #2278

Draft
omar-polo wants to merge 3 commits into
mainfrom
op/refactor-config
Draft

config: unify Get{Source,Store,Destination} behaviour#2278
omar-polo wants to merge 3 commits into
mainfrom
op/refactor-config

Conversation

@omar-polo

Copy link
Copy Markdown
Contributor
  • let all of them to resolve internally the "at aliases" syntax
  • all of them return a map or an error, not a boolean
  • they verify internally that location is set

The visible changes are:

  • the message for an alias not found or a location missing is
    slightly different
  • passphrase_cmd gets replaced everywhere: I've checked all the
    currently packaged importers and exporters, and no-one is using it,
    I'm fine with this trade-off for now, in the near future it'll get
    replaced by a better mechanism anyway.

(plus two minor improvements while here, this is the last step before overloading the config resolution.)

we're moving to a world where we use the config more often, so make
sure the object is always set at configuration creation time.
Copilot AI review requested due to automatic review settings July 21, 2026 20:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors configuration lookup to unify GetSource, GetDestination, and GetRepository behavior: each now resolves @alias tokens internally (including root overrides), validates that location is present, and returns (map[string]string, error) instead of a boolean flag. It also centralizes passphrase command resolution into config resolution and updates subcommands/tests to rely on AppContext providing a non-nil config by default.

Changes:

  • Reworked config.Config getters to share a common resolution path (get + resolve) and introduced sentinel errors (ErrNotFound, ErrNoLocation).
  • Updated subcommands (backup, ptar, restore, config) to use the new error-returning getters and to stop duplicating @alias resolution logic.
  • Simplified tests by removing manual config.NewConfig() setup where AppContext.NewAppContext() now initializes ctx.Config.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
subcommands/sync/sync_test.go Removes manual config initialization now handled by NewAppContext().
subcommands/sync/sync_coverage3_test.go Same: relies on default-initialized ctx.Config.
subcommands/restore/restore.go Switches exporter config resolution to ctx.Config.GetDestination(...) with error handling.
subcommands/ptar/ptar.go Switches importer config resolution to ctx.Config.GetSource(...) with error handling.
subcommands/ptar/ptar_coverage2_test.go Removes manual config init; keeps source setup via ctx.Config.Sources[...].
subcommands/ptar/ptar_coverage_test.go Updates tests to new error messages / behavior and removes nil-config workaround.
subcommands/ptar/ptar_cov80_test.go Removes manual config init; continues configuring peer repositories through ctx.Config.
subcommands/config/config.go Updates config validation paths to use error-returning getters.
subcommands/backup/backup.go Replaces local @source resolution/merging logic with GetSource + map merge.
subcommands/backup/backup_faults_test.go Updates expectations to new standardized error message.
subcommands/backup/backup_coverage2_test.go Removes manual config init and updates error message assertions.
subcommands/backup/backup_cov80_test.go Removes manual config init in option-inheritance coverage test.
config/resolve.go Adds shared config entry resolution, including raw: stripping and passphrase_cmd execution.
config/old.go Adjusts old-config structures to the new map[string]map[string]string representation.
config/config.go Introduces unified getter behavior (get) and sentinel errors; updates getter signatures.
config/config_test.go Updates tests for new types/signatures and adds coverage for ErrNoLocation.
config/config_extra_test.go Updates destination/source/repo tests to new getter semantics and @ usage.
appcontext/appcontext.go Ensures NewAppContext() always initializes Config to a non-nil config object.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread config/config.go
Comment thread config/resolve.go
Comment thread config/config.go
Copilot AI review requested due to automatic review settings July 21, 2026 20:10
@omar-polo
omar-polo force-pushed the op/refactor-config branch from 1f089de to ee47366 Compare July 21, 2026 20:10
@omar-polo
omar-polo force-pushed the op/refactor-config branch from ee47366 to 0999ae9 Compare July 21, 2026 20:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

config/config.go:75

  • GetDestination forwards the kind string as "source", which will produce incorrect error messages (e.g., "source configuration not found") for destination lookups.
	return c.get(name, "destination", c.Destinations)

Comment thread config/resolve.go
Comment thread subcommands/config/config.go
Comment thread subcommands/config/config.go
Comment thread subcommands/config/config.go
Comment thread subcommands/config/config.go
Copilot AI review requested due to automatic review settings July 21, 2026 20:14
@omar-polo
omar-polo force-pushed the op/refactor-config branch from 0999ae9 to 989ef93 Compare July 21, 2026 20:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (4)

subcommands/config/config.go:142

  • normalizeName strips the "@" prefix, but Config.GetSource now treats non-"@" inputs as literal locations. As a result, plakar config source check <name> will try to create an importer with location="" instead of looking up the configured source entry.
			imp, err := importer.NewImporter(ctx.GetInner(), ctx.ImporterOpts(), cfg)

subcommands/config/config.go:153

  • normalizeName strips the "@" prefix, but Config.GetDestination now treats non-"@" inputs as literal locations. This makes plakar config destination check <name> attempt to use location="" instead of resolving the configured destination.
			exp, err := exporter.NewExporter(ctx.GetInner(), ctx.ExporterOpts(), cfg)

subcommands/config/config.go:276

  • Same issue as the check subcommand: ping passes a bare name into GetSource, which now means "literal location" rather than alias lookup. This will break plakar config source ping <name>.
			imp, err := importer.NewImporter(ctx.GetInner(), ctx.ImporterOpts(), cfg)

subcommands/config/config.go:291

  • Same issue as the check subcommand: ping passes a bare name into GetDestination, which now means "literal location" rather than alias lookup. This will break plakar config destination ping <name>.
			exp, err := exporter.NewExporter(ctx.GetInner(), ctx.ExporterOpts(), cfg)

Comment thread config/config.go
Copilot AI review requested due to automatic review settings July 21, 2026 20:19
@omar-polo
omar-polo force-pushed the op/refactor-config branch from 989ef93 to b643222 Compare July 21, 2026 20:21
* let all of them to resolve internally the "at aliases" syntax
* all of them return a map or an error, not a boolean
* they verify internally that location is set

The visible changes are:
* the message for an alias not found or a location missing is
  slightly different
* passphrase_cmd gets replaced everywhere: I've checked all the
  currently packaged importers and exporters, and no-one is using it,
  I'm fine with this trade-off for now, in the near future it'll get
  replaced by a better mechanism anyway.
@omar-polo
omar-polo force-pushed the op/refactor-config branch from b643222 to cf16611 Compare July 21, 2026 20:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (5)

subcommands/config/config.go:128

  • Config.GetSource only resolves configured sources when the argument starts with "@". Calling it with a plain config name (e.g. "mysrc") returns {location: "mysrc"} and ignores the configured section, so plakar source check <name> will validate the wrong thing (and likely fail) even when the config exists.
		name := args[0]
		if !hasFunc(name) {
			return fmt.Errorf("%s %q does not exist", cmd, name)
		}

subcommands/config/config.go:153

  • Same issue as the source branch above: Config.GetDestination treats a non-"@" argument as a literal location, so plakar destination check <name> won’t actually use the configured destination section.
		case "destination":
			cfg, err := ctx.Config.GetDestination(name)
			if err != nil {
				return err
			}
			exp, err := exporter.NewExporter(ctx.GetInner(), ctx.ExporterOpts(), cfg)

subcommands/config/config.go:258

  • Config.GetSource only resolves configured sources when the argument starts with "@". In the ping subcommand, calling it with the plain config name makes plakar source ping <name> ping {location: "<name>"} instead of the configured source.
		name := args[0]
		if !hasFunc(name) {
			return fmt.Errorf("%s %q does not exist", cmd, name)
		}

subcommands/config/config.go:291

  • Same issue as the source ping branch: Config.GetDestination treats a non-"@" argument as a literal location, so plakar destination ping <name> won’t ping the configured destination.
		case "destination":
			cfg, err := ctx.Config.GetDestination(name)
			if err != nil {
				return err
			}
			exp, err := exporter.NewExporter(ctx.GetInner(), ctx.ExporterOpts(), cfg)

config/resolve.go:66

  • resolve() iterates a map, so the relative handling of passphrase vs passphrase_cmd is currently nondeterministic when both keys are present: whichever key happens to be processed last wins. That can lead to flaky behavior depending on map iteration order. Make precedence explicit (e.g., prefer an explicitly configured passphrase, and only fall back to passphrase_cmd when no passphrase is set).
	for k, v := range conf {
		if k == "passphrase_cmd" {
			v, err := getPassphraseFromCommand(v)
			if err != nil {
				return nil, err

Comment thread subcommands/config/config.go
Comment thread config/resolve.go
return "", fmt.Errorf("passphrase_cmd returned too many lines")
}

return pass, nil

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

go home you're drunk. bufio.ScanLines, the default split function, says:

// ScanLines is a split function for a [Scanner] that returns each line of
// text, stripped of any trailing end-of-line marker. The returned line may
// be empty. The end-of-line marker is one optional carriage return followed
// by one mandatory newline. In regular expression notation, it is \r?\n.
// The last non-empty line of input will be returned even if it has no
// newline.

Copilot AI review requested due to automatic review settings July 21, 2026 20:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (4)

subcommands/config/config.go:142

  • ctx.Config.GetSource now interprets non-"@" arguments as a literal location, so check source <name> will try to build an importer with location=<name> instead of looking up the configured source section. Prefix the section name with "@" when calling GetSource here.
		case "source":
			cfg, err := ctx.Config.GetSource(name)
			if err != nil {
				return err
			}
			imp, err := importer.NewImporter(ctx.GetInner(), ctx.ImporterOpts(), cfg)

subcommands/config/config.go:154

  • ctx.Config.GetDestination now treats non-"@" arguments as a literal location; check destination <name> should look up the destination section, so pass it as an alias ("@") here.
		case "destination":
			cfg, err := ctx.Config.GetDestination(name)
			if err != nil {
				return err
			}
			exp, err := exporter.NewExporter(ctx.GetInner(), ctx.ExporterOpts(), cfg)
			if err != nil {

subcommands/config/config.go:277

  • Same issue as check: ping source <name> passes a bare section name into GetSource, which is now treated as a literal location. Prefix with "@" so the configured source section is resolved.
		case "source":
			cfg, err := ctx.Config.GetSource(name)
			if err != nil {
				return err
			}
			imp, err := importer.NewImporter(ctx.GetInner(), ctx.ImporterOpts(), cfg)
			if err != nil {

subcommands/config/config.go:292

  • Same issue as check: ping destination <name> needs to resolve the named destination section, but GetDestination treats bare strings as literal locations. Prefix with "@" here.
		case "destination":
			cfg, err := ctx.Config.GetDestination(name)
			if err != nil {
				return err
			}
			exp, err := exporter.NewExporter(ctx.GetInner(), ctx.ExporterOpts(), cfg)
			if err != nil {

@omar-polo
omar-polo marked this pull request as draft July 21, 2026 23:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants