-
Notifications
You must be signed in to change notification settings - Fork 1
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
feat(diff): diff without producing temporary files #128
base: main
Are you sure you want to change the base?
Conversation
e4aefb2
to
82b0f22
Compare
One more thing: I am not sure this handles renames/moves well. I am looking into using the Git extension API and |
Thank you so much for taking a stab at this, Lorenz!! 🙇 This PR is still marked as This helps both with reviewing and also would make it easier in the future if we need to bring the "ignore temp files" feature back. |
This would also be a good resource to consult regarding virtual documents straight from the docs https://code.visualstudio.com/api/extension-guides/virtual-documents |
4e41dc5
to
16ead5a
Compare
Done, see #129.
Could you please elaborate how this is relevant? I fail to understand. |
16ead5a
to
3154614
Compare
5f71ff9
to
6a91efa
Compare
I believe "virtual documents" are what we (should?) use for in-memory diffing (vs on-disk saved temp) documents for the same purpose. |
7939855
to
d8f911e
Compare
No. This is the reason I refer to microsoft/vscode#55110 in OP. Specifically in microsoft/vscode#55110 (comment) the authors of the GitLens extension (who probably went far, far deeper down the rabbit hole), say that |
throw new Error(`Failed access Git repository.`) | ||
} | ||
|
||
const changes: Change[] = await repo?.diffBetween(range.old, range.new) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const changes: Change[] = await repo?.diffBetween(range.old, range.new) | |
const changes = await repo?.diffBetween(range.old, range.new) |
d8f911e
to
e51a0c0
Compare
@lorenzleutgeb as discussed synchronously, there's a major architectural design decision coming with this PR that hasn't been communicated in advance: the diff is no longer sourced via httpd, which can be configured to be any remote seed other than This could either be a great idea (yay "local-first") or the opposite (diffs must be local, or made local before shown, which involves using the I'll need to come back to this with a clearer head in a few days, discuss it with the team and come back to you. Regardless, that's an epic contribution in itself, without even taking into account that its on the same day you checked the repo's source for the first time, and working mainly on our most complicated file! 👏 The options onwards from here are:
My gut feeling says we might end up with the third option. I'll be able to share more in a few days. Thank you so much for being excited about this project and going out of your way to actionably help! |
Alright. Let me just write down my view so that you have a record of it. I'd be very happy if you could include my opinion somehow in your discussion with the team. Browsing Repositories on Remote Radicle NodesOne of the reasons for communicating with In my imagination, the VSCode extension would instruct the local node to gossip with the network, in order to get a the state of the repository on the remote node. In short: It downloads the repository over the Radicle network. Then, since the user is not interested in actually checking out a worktree for this repository, you could still use the local bare clone of the repository to run diffs. For example, to browse the issues of
The main reason for creating the (worktree) repository
We can also do this for patches:
Note that for all of this, I have not created a worktree of either of the two repos In fact this approach is very much "local first". Apart from the initial gossiping, I can browse the repository, without any further networking. Everything will be fast. You might now be inclined to argue that obtaining the initial copy for the repository is costly, but I concur. Many repositories are small. And as Radicle is used for bigger and bigger repositories, this problem will have to be solved on another layer anyway (probably enabling shallow fetching). Additionally, copies of the same repo will end up as remotes to the same bare Git repository. This means that Git objects are shared, thus browsing a copy of a repository that you already have locally will be very efficiently accelerated by Git. What you need Remote DevelopmentThere's one more angle: Remote development. It might be the case that you intended this design to grow into supporting remote development in some way, i.e. running the VSCode extension on a laptop but the Radicle node on a workstation/server. I am doing this. I run a VSCode client on Windows machine, and connect via VSCode Remote-SSH and Tailscale SSH to a NixOS workstation, which in turn runs Radicle. This works flawlessly, and already perfectly fits my remote development workflow. Building/compiling happens on the workstation. My Radicle node also runs on the workstation, and the extension is snappy and keeping up perfectly well. I even develop the VSCode extension using my remote setup. To make { "remote.SSH.defaultForwardedPorts": [{ "name": "http-alt", "localPort": 8080, "remotePort": 8080 }]} Light Nodes/ClientsIt might be the case that Radicle develops in a direction where something like a "light node" (browsing only) is required. However, I don't think that the VSCode extension is the place that should pioneer anything in that direction. VSCode is for developers, and if you're somewhat serious about developing software on using Radicle, you will use a "full node". Adding support in this direction is premature at the current stage. Unneeded complexity that decreases your velocity. Acting on Behalf of Remote NodesThere might be a time where I can sign something locally using a different key than my own node key. E.g. I use node A to publish updates for node B. If this ever becomes a thing I really hope it's gonna be native to Heartwood (or at least very low level in the stack), and not via Grokking Remote NodesApart from the technical design, I also think that what I am proposing is much easier to reason about for the user. I think it is easier to conceptualize that the VSCode extension is a "supercharger" /"batteries" for ConclusionThe Radicle VSCode extension SHOULD NOT be the interface to an arbitrary remote Radicle node. Instead, it SHOULD be the interface to the local node that is part of the Radicle network. It should wrap the steps I did above using This discussion definitely turned my view on this extension upside down. I misunderstood the design completely. |
I have identified an issue with this PR: As things are currently set up, there might be objects in the object database of the bare repository in
The result is that when an affected patch is expanded in the patch list, no file changes are shown. There are at least three approaches to solve this. 1. FetchingThe VSCode Extension would have to figure out from which remote to fetch in order to obtain the required objects. I have no idea how that could be implemented. 2. Share the Git Object Database2.A Use the Worktree MechanismInstead of having two decoupled repositories, make the working copy a worktree of the bare repo. This can be achieved as follows:(
2.B Use the "alternates" MechanismIt is possible to create a file in |
|
This takes a different approach to resolving cytechmobile#94 Use the Git integration for Visual Studio Code (an extension that is bundled with VSCode and neither be disabled or uninstalled, thus can be effectively considered part of VSCode) to read files directly off of Git. Signed-off-by: Lorenz Leutgeb <[email protected]>
Missing typings. See cytechmobile#130 Signed-off-by: Lorenz Leutgeb <[email protected]>
8a0cf4f
to
f2dd59d
Compare
Thanks so much for this contribution @lorenzleutgeb ! 🙏🏼 I'd like to add some context:
This is exactly the direction we've followed in the Radicle IntelliJ plugin, so it makes perfect sense for me.
There is a lot of speculation in the discussion above as to why we depend on httpd, so please allow me to clarify: Originally, in the IntelliJ plugin (that predated this one, since it was the first one our team started working on) we were using only the Command Line Interface (CLI). This made sense for an Integrated Development Environment (IDE) where we wanted a single dependency - rather than needing to ask our user to define both the path to the CLI and the httpd endpoint. However, the CLI does not return json (or machine readable output, in general). As the httpd already does, the core team advised us to just use that instead because adding This is the only reason we're relying on httpd today. I do still think the CLI is a better option for IDEs, but I do understand why it doesn't do that still and the httpd is a good compromise for the time being. For broader context, I'm also linking here a zulip topic where it was discussed how to address this - and where it also mentioned that the upcoming Terminal UI (TUI) would also need this in the CLI.
@lorenzleutgeb using the bare repo is an interesting approach, but, I am wondering: would we still have this problem if we had a full working copy of the radicle repo that we were working in ? Would cloning a radicle repository in cc @JChrist |
I'm reply to @gsaslis.
I disagree. I think what is crucial here is to acknowledge that just slapping
I realized the situation about missing stable plumbing commands only after opening this PR. However, I also immediately took action, and Heartwood now contains a new My learnings from this PR and its discussion is the immediate motivation. I'll probably step on toes, but: It appears to me that the first bottleneck for development of this extension was missing plumbing commands, but it is still bottlenecked by I am trying to go back to the root here and implement what is necessary as commands. The deployment story for users will be simpler ("Why do I need to run a server?!"), more reliable (less moving parts without If anyone wants to be a step ahead: The VSCode Extension will likely need type definitions based on the datatypes defined in Rust, because that currently defines the shape of the data exchanged both via commands and the control socket.
Fetching was my first suggestion, see Item in the comment you are quoting. I am saying that the problem exists for a working copy. Fetching can of course copy the correct objects over, but only if you know what to fetch. I am not too sure on the Radicle terminology here, but the problem lies with patches on remotes that are not "followed" (?!). You'd have to go and fetch the head of a patch from a specific NID. So a simple Please note that there is another benefit to my workaround: With it, there's no need to copy files between the bare repo and your working copy. The Git object database of the working copy is extended with the one of the bare repo. One copy is enough! Also, this does not leak any private data, because the "extension" is one-way. I'll go one step further and say that really working copies should use Git's Worktree feature. It was made for that. |
} | ||
|
||
return undefined | ||
const repo = gitExtensionApi.getRepository(Uri.file(repoRoot)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of getting the working copy here, it would be possible to use the bare repository. This would resolve issues of missing objects.
@@ -0,0 +1,348 @@ | |||
/* --------------------------------------------------------------------------------------------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a vendored file we should have a comment mentioning the fact and also its source, along with any changes vs the source. See https://github.com/cytechmobile/radicle-vscode-extension/blob/main/src/webviews/src/assets/codicon.css#L1-L11 for how it's already handled in the repo.
Also we could benefit from a filename that better communicates that its conents are typings specifically for the native git extension.
|
||
// Ignore, since this file is vendored from VSCode and should not be changed. | ||
// See `CONTRIBUTING.md`. | ||
'src/types/git.ts', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the file only requires auto-fixable issues, it's preferable to just apply them, and not add this ignore.
If that's not the case then let's go with the contents as they are.
const gitExtension = vscode.extensions.getExtension<GitExtension>(gitExtensionId) | ||
|
||
if (gitExtension === undefined) { | ||
throw new Error(`Could not load VSCode Git extension with id '${gitExtensionId}'`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the chances that this ever breaks are very low, we still should handle the case of it throwing.
It could be either falling back to httpd or just notifying the user with an error message of what happened.
] | ||
} | ||
|
||
return changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this repo we're avoiding any non-trivial return statements. All such cases should instead be an assignment to a well named function and then a return of that one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for spending your time on this fundamental improvement of the extension's tech! 🙇
I definitely would like to explore further opportunities for independence from httpd over time too, wherever those would make sense.
There are still a couple of things left that I'd like to check on this PR and I will get to it ASAP, but until then I wanna say that it looks great and I've only been able to find a couple of nits.
This takes a different approach to resolving #94. Uses the Git integration for Visual Studio Code (an extension that is bundled with VSCode and can neither be disabled or uninstalled, thus can be effectively considered part of VSCode) to read files directly off of Git, eliminating the need for temporary files, and thus all other dependent hacks.
I found that GitLens in fact registers it's own
FileSystemProvider
, which might have some additional benefits. However, I don't think that this is necessary in the case of the Radicle VSCode extension (yet).For reference, the implementation of
FileSystemProvider
that this PR uses is at https://github.com/microsoft/vscode/blob/1.88.1/extensions/git/src/fileSystemProvider.tsWith regards to
TextDocumentContentProvider
refer to microsoft/vscode#55110 for a discussion of its limitations.