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

Add Branch Selection for coffee_install() #242

Closed
wants to merge 4 commits into from

Conversation

tareknaser
Copy link
Collaborator

Description

Add branch selection for coffee_install and display plugin git HEAD in coffee list.
Fixes #205

Changes

  • Added Repository::git_head() to retrieve the repository's git HEAD.
  • Added an optional branch parameter to coffee_install() for branch selection during installation.
  • Implemented git_upgrade_with_git_head() for checkout using a specific git HEAD.
  • Updated cmdcoffee_plugin, and coffee httpd to pass the branch value.
  • Modified coffee list output to display the git HEAD of plugins.

Testing

coffee install <plugin_name> --branch <branch_name>

This function will come in handy when we want to restore the state of a repository on disk after upgrading a plugin

Signed-off-by: Tarek <[email protected]>
This commit adds an optional parameter to coffee_install() method that makes it possible to specify a branch when installing a plugin.

The logic is:
- get information about current status before switching (repoisitory branch and plugin git head)
- switch to the branch
- restore old information and rollback

A function git_upgrade_with_git_head was implemented to handle checking out using a specfic git_head

we are using the repository git head to save current status and roll back to it since it's safer than using just the branch (we fetch origin so maybe the branch was updated. we want to be back to the same commit)

also, cmd, coffee_plugin and coffee httpd were upgraded to pass the branch value

Signed-off-by: Tarek <[email protected]>
Since we now may have separate git heads for plugin and repository, we print the git HEAD of the plugin to the user

Signed-off-by: Tarek <[email protected]>
Copy link

netlify bot commented Feb 23, 2024

Deploy Preview for coffee-docs ready!

Name Link
🔨 Latest commit d77053b
🔍 Latest deploy log https://app.netlify.com/sites/coffee-docs/deploys/65d907a4608e570008c22b65
😎 Deploy Preview https://deploy-preview-242--coffee-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

@vincenzopalazzo vincenzopalazzo left a comment

Choose a reason for hiding this comment

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

I think that this implementation is a little bit too complex for what we need to do

Comment on lines +43 to +45
/// return the git head of the repository.
fn git_head(&self) -> Option<String>;

Copy link
Contributor

Choose a reason for hiding this comment

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

does not make sense to have this inside the repository trait

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

good point. I will update it

Comment on lines +339 to +342
/// return the git head of the repository.
fn git_head(&self) -> Option<String> {
self.git_head.clone()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Move this as a struct method and not an a trait implementation

Comment on lines +258 to +279
// if the branch is specified, we need to save current git_head
// and checkout the branch
let current_git_head = repo.git_head();
let current_plugin_commit = plugin.commit.clone();
if let Some(branch) = branch.clone() {
log::debug!("checking out branch: {branch}");
if current_git_head.is_none() {
return Err(error!("unable to get the current git head"));
}
let updated_status =
git_upgrade_with_branch(repo.url().path_string.as_str(), &branch, verbose)
.await?;
log::debug!("updated status: {:?}", updated_status);

let repository = git2::Repository::open(repo.url().path_string.as_str())
.map_err(|err| error!("{}", err.message()))?;

// get commit id after the checkout
let commit = commit_id!(repository);
log::debug!("commit id after the checkout: {commit}");
plugin.commit = Some(commit);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

IMHO to much code for just sh!("git checkout {branch}")?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can see some potential issues with simply using git checkout {branch}:

  • If the branch is new (not fetched yet), we need to git fetch origin first.
    • To make sure we are returning to the expected state after switching back, we need the repository's Git HEAD, not just the current branch. This is because the branch might have been updated remotely (when we ran git fetch origin), and we want to go back to the exact commit the user was on.
    •  We need to verify that the repository's Git HEAD information exists (introduced in a previous PR as an Option to be backward compatible)
  • The plugin's commit field is updated during installation and then reverted afterward. Otherwise, we have false information.

Do you think that any of these steps is redundant?

Copy link
Contributor

Choose a reason for hiding this comment

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

my point is that we can do all with just a couple of git command, with your solution I do not see any fetch anywhere too and we need to make sure that your code is correct, otherwise we will have the same problem that we had with the upgrade logic

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

git_upgrade_with_branch() does git fetch origin


if branch.is_some() {
// we can safely unwrap here because we have checked it before
let current_git_head = current_git_head.unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

the safety comment start with // SAFETY: ...

Comment on lines +331 to +345
if branch.is_some() {
// we can safely unwrap here because we have checked it before
let current_git_head = current_git_head.unwrap();
log::debug!("checking out to git head: {current_git_head}");
// rollback to the previous git head
let updated_status = git_upgrade_with_git_head(
repo.url().path_string.as_str(),
&current_git_head,
verbose,
)
.await?;
log::debug!("updated status: {:?}", updated_status);

plugin.commit = current_plugin_commit;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

wow this install method is starting to be 2 pages long?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree!
We can keep coffee install for just installing and configuring plugins and introduce coffee upgrade --plugin <plugin_name> --branch <branch_name> for upgrades and branch switching

Copy link
Contributor

Choose a reason for hiding this comment

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

No, my point is that the code that we are writing the code of the install is not good at all. Please see some of my PR that I am refactoring it.

In addition, both install and upgrade command will run the same logic and with your code we should duplicate the checkout logic. This is error prone

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, my point is that the code that we are writing the code of the install is not good at all.

Ok. how do you think I can make it better? I explained why we need the extra code in install() in this conversation #242 (comment).
Do you think that any of these steps is redundant or should be implemented in another way?

In addition, both install and upgrade command will run the same logic and with your code we should duplicate the checkout logic. This is error prone

They will have the same logic because they will do very similar tasks. The function git_upgrade_with_commit() will be reused in coffee upgrade --plugin <plugin_name>.
We can start with implementing coffee upgrade --plugin <plugin_name> and then use it directly from coffee install --branch <branch_name>. This way we don't duplicate code

@@ -25,7 +25,7 @@ pub async fn clone_recursive_fix(repo: git2::Repository, url: &URL) -> Result<()
Ok(())
}

pub async fn git_upgrade(
pub async fn git_upgrade_with_branch(
Copy link
Contributor

Choose a reason for hiding this comment

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

why changing the name here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

because I added another function that uses the git commit to upgrade

Copy link
Contributor

Choose a reason for hiding this comment

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

I do not see the point of changing the name, due that there is no git upgrade command in git

Copy link
Contributor

Choose a reason for hiding this comment

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

Moreover, git uses always a branch there is never a without_branch cases


let (local_commit, _) = get_repo_info!(repo);

let mut cmd = format!("git fetch origin\n");
Copy link
Contributor

Choose a reason for hiding this comment

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

let mut cmd = "git fetch origin\n";

format! is not needed

Comment on lines +52 to +57
pub async fn git_upgrade_with_git_head(
path: &str,
git_head: &str,
verbose: bool,
) -> Result<UpgradeStatus, CoffeeError> {
use tokio::process::Command;
Copy link
Contributor

Choose a reason for hiding this comment

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

idk if this is a good idea, the checkout is just git checkout <branch-name>

Why we need to use all this code?

@@ -22,6 +22,7 @@ pub fn show_list(coffee_list: Result<CoffeeList, CoffeeError>) -> Result<(), Cof
term::format::bold(String::from("Language")),
term::format::bold(String::from("Name")),
term::format::bold(String::from("Enabled")),
term::format::bold(String::from("Git HEAD")),
Copy link
Contributor

Choose a reason for hiding this comment

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

a user need also a git PHD to understand what is a git HEAD? Idk if this is necessary.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We already print the git HEAD to the user with coffee remote list
If we add the possibility to manage the branch for the plugin in separation from the repository, I think we have to print it in coffee list

Copy link
Contributor

Choose a reason for hiding this comment

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

Please call it commit there is no meaning to complicate a simple things with big words.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure. Do you want me to rename "Git HEAD" to "commit" in coffee remote list output too?

Comment on lines +107 to +114
#### Specifying a branch for installation

To install a plugin from a specific branch, you simply need to run.

```bash
coffee install <plugin_name> --branch <branch_name>
```

Copy link
Contributor

Choose a reason for hiding this comment

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

we should not document every single command possibility otherwise our documentation will be always uncompleted

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Right. I can remove this section

Copy link
Contributor

Choose a reason for hiding this comment

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

but we should came up with a way to document optional parameters

@vincenzopalazzo
Copy link
Contributor

Closing in favor of #248

@tareknaser tareknaser deleted the install-branch branch March 7, 2024 15:22
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.

Add Branch Specification for Plugin Installation
2 participants