Skip to main content

at_forwarders

Macro at_forwarders 

Source
macro_rules! at_forwarders {
    (
        $view:ident, $field:ident, $client:literal,
        bare { $( fn $bn:ident( $($ba:ident: $bt:ty),* $(,)? ) -> $br:ty; )* }
        dir  { $( fn $dn:ident( $($da:ident: $dt:ty),* $(,)? ) -> $dr:ty; )* }
        $( raw  { $( fn $rn:ident( $($ra:ident: $rt:ty),* $(,)? ) -> $rr:ty => $rtgt:ident; )* } )?
    ) => { ... };
}
Expand description

Generate the cwd-bound forwarders for a CLI wrapper’s …At view.

Each CLI wrapper (vcs-git, vcs-jj, vcs-github, vcs-gitlab, vcs-gitea) exposes a cwd-bound view — GitAt, JjAt, GitHubAt, GitLabAt, GiteaAt — that holds a reference to the client plus a pre-bound dir, and re-exposes the client’s methods with dir already supplied. The forwarder bodies are byte-identical across the five backends but for a handful of names, so they live here once instead of as a copied macro_rules! per crate:

  • $view — the bound view type (e.g. GitAt). It must be generic over <'a, R: ProcessRunner> and have a field named $field holding the client plus a dir: &'a Path field.
  • $field — the inner field naming the client (e.g. git, gh, glab, tea).
  • $client — a string literal naming the client type, used in the generated doc strings and rendered as an intra-doc link (e.g. "Git"[`Git`]).
  • bare { … } — methods forwarded verbatim to self.$field. Reserve this for the genuinely dir-independent calls (version, capabilities, a clone/git_clone that names its own destination): the view drops dir entirely, so a bare method never touches it.
  • dir { … } — methods that take self.dir as their first argument.
  • raw { fn view(args…) -> Ret => target; … } — the raw escape hatches (run/run_raw/run_args/run_raw_args). These used to sit in bare, so git.at(dir).run(…) silently ran in the process cwd, not the bound dir — a bound handle whose raw call could hit a different repository (M15/T-035). They are now bound: the view method view forwards to the client’s dir-taking target (self.$field.target(self.dir, args…)), so a raw call through the view runs in dir like every other …At method. The process-cwd escape hatch is still there — call run/run_raw/… on the client itself (git.run(…)), not through .at(dir).

The argument and return types in the method lists resolve in the calling crate, so they are written exactly as that wrapper’s own methods are. The ProcessRunner bound is fully qualified (::processkit::ProcessRunner) so the expansion compiles regardless of which items the caller has imported.

vcs_cli_support::at_forwarders! {
    GitAt, git, "Git",
    bare { fn version() -> Result<String>; }
    dir  { fn status() -> Result<Vec<StatusEntry>>; }
    raw  { fn run(args: &[String]) -> Result<String> => run_in; }
}