Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Canonical URI identity provider #180582

Open
joyceerhl opened this issue Apr 21, 2023 · 1 comment
Open

Proposal: Canonical URI identity provider #180582

joyceerhl opened this issue Apr 21, 2023 · 1 comment
Assignees
Labels
Milestone

Comments

@joyceerhl
Copy link
Collaborator

joyceerhl commented Apr 21, 2023

In both edit sessions and workspace trust, we need to solve the problem of disambiguating URIs across filesystems. The approaches currently taken are:

  • Edit sessions combines the remote, branch/tag name, and SHA to determine that two workspace snapshots occurring in two different filesystems are equal
    • Edit sessions does not know that repositories cloned with different protocols (HTTPS / SSH) are the same, since the conversion from a HTTPS to SSH URL is not standard across remote git providers
  • Workspace trust uses the getCanonicalUri APi from the remote proposal to determine that a folder from the local filesystem which is mounted into a remote has already been trusted in the local filesystem
    • Workspace trust does not know that a repository has been trusted in say vscode.dev when it is cloned to the local filesystem and reopened in VS Code desktop
    • Also, it special cases vscode-vfs URIs by manipulating the authority field in order to know that two vscode-vfs URIs pointing to different branches on the same repository are in fact referencing the same repository (since vscode-vfs URIs encode the branch, tag, PR in the authority and do not compare equal when stringified)

This results in friction for users, who must repeatedly trust the same repository across different filesystems, and who are unable to roam workspace state for the same repository across two different filesystems if they have been cloned with different remotes.

To address both these scenarios, we would like to introduce an API proposal for transforming URIs if a URI has one or more alternate identities. This is not an inherently source control-specific concept, since you could have a folder on a local filesystem which is mounted into a container and not backed by source control, and in that scenario it should be possible to say that the local file:// URI is equivalent to the vscode-remote:// URI. It is also not an inherently remote-specific concept, since two file:// URIs for the same repository on two different filesystems should be resolvable to the same identity.

Prior art:

/**
* Get the canonical URI (if applicable) for a `vscode-remote://` URI.
*
* @returns The canonical URI or undefined if the uri is already canonical.
*/
getCanonicalURI?(uri: Uri): ProviderResult<Uri>;

export interface EditSessionIdentityProvider {
/**
*
* @param workspaceFolder The workspace folder to provide an edit session identity for.
* @param token A cancellation token for the request.
* @returns A string representing the edit session identity for the requested workspace folder.
*/
provideEditSessionIdentity(workspaceFolder: WorkspaceFolder, token: CancellationToken): ProviderResult<string>;

Initial proposal:

declare module 'vscode' {
    export namespace workspace {
        export function registerCanonicalUriIdentityProvider(scheme: string, provider: CanonicalUriIdentityProvider): Disposable; // There can be multiple providers for the same scheme
    }

    export interface CanonicalUriIdentityProvider {
        provideCanonicalUriIdentity(uri: Uri, token: CancellationToken): ProviderResult<CanonicalUriIdentity | CanonicalUriIdentity[]>;
    }

    export interface CanonicalUriIdentity {
        host: string;
        metadata: string;
    }
}

Example usage:

Provider URI scheme URI authority Identity
Remote extensions vscode-remote containers { host: 'file', metadata: 'filepath' }
Builtin GitHub extension file `` { host: 'github', metadata: 'microsoft/vscode' }
GitHub Repositories extension vscode-vfs github { host: 'github', metadata: 'owner/repo' }
Azure Repos extension vscode-vfs azurerepos { host: 'azurerepos', metadata: 'org/project/repo' }

An alternative solution for workspace trust is to instead leverage #179898 and declare that a workspace has been trusted before by storing this information for StorageScope.Workspace and StorageTarget.User, which will lead to that information roamed via edit sessions. However that won't allow workspace trust to move away from the hack it does for vscode-vfs URIs, since edit sessions takes the branch and SHA into account, and vscode-vfs URIs bake that information in as well.

@joyceerhl
Copy link
Collaborator Author

Feedback from API sync

  • Canonical URI is somewhat vague, ideally we use a different name
  • We have asCanonicalUri already in the remote resolver API, this proposal would supersede that

Additional feedback from @sbatten

  • s/canonical/external/ doesn't really work if we want this proposal to supersede the remote resolver asCanonicalUri
  • Can the provider registration and the caller specify the scheme of the URI to return so that the result is not ambiguous
  • Workspace trust needs to know what to display as the 'host' and 'path', what should be displayed for https remote URLs?
    • Contribute a resource label formatter for https and github.com URLs and reference that when rendering trusted folders and workspaces?

Updated proposal shape:

declare module 'vscode' {

	export namespace workspace {
		/**
		 *
		 * @param scheme The URI scheme that this provider can provide canonical URI identities for.
		 * A canonical URI represents the conversion of a resource's alias into a source of truth URI.
		 * Multiple aliases may convert to the same source of truth URI.
		 * @param provider A provider which can convert URIs for workspace folders of scheme @param scheme to
		 * a canonical URI identifier which is stable across machines.
		 */
		export function registerCanonicalUriIdentityProvider(scheme: string, provider: CanonicalUriIdentityProvider): Disposable;

		/**
		 *
		 * @param uri The URI to provide a canonical URI identity for.
		 * @param token A cancellation token for the request.
		 */
		export function getCanonicalUri(uri: Uri, options: CanonicalUriRequestOptions, token: CancellationToken): ProviderResult<Uri>;
	}

	export interface CanonicalUriIdentityProvider {
		/**
		 *
		 * @param uri The URI to provide a canonical URI identity for.
		 * @param token A cancellation token for the request.
		 * @returns The canonical URI identity for the requested URI.
		 */
		provideCanonicalUriIdentity(uri: Uri, options: CanonicalUriRequestOptions, token: CancellationToken): ProviderResult<Uri>;
	}

    export interface CanonicalUriRequestOptions {
        targetScheme: string;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants