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

If two artifacts provide the same file, re-link or re-copy that file from the artifact left after the other was undeployed/uninstalled. #3455

Merged
merged 5 commits into from
Aug 22, 2024

Conversation

mitchell-as
Copy link
Contributor

@mitchell-as mitchell-as commented Aug 20, 2024

TaskDX-2913 We track individual file ownership on the artifact level

The idea behind this PR is to:

  • Retain the current of behavior of not modifying any currently deployed files. That is, if two artifacts both provide the same file, the one installed first "wins".
  • Change the behavior of deleting any currently deployed files from an artifact. If two artifacts both provide the same file, when one of them is uninstalled, re-link or copy the file from the remaining artifact that is still installed.

For example, given the following two packages:

  • state install hello, which provides a bin/main executable such that state exec main prints Hello world!.
  • state install hello-again, which provides a bin/main executable such that state exec main prints Hello world again!.

Here's a scenario:

  1. state install hello
  2. state install hello-again
  3. state exec main --> prints Hello world! from hello, which "wins" by providing bin/main first.
  4. state uninstall hello --> identifies that hello-again also provides bin/main, and re-links/re-deploys it after uninstalling hello.
  5. state exec main --> prints Hello world again!
  6. state uninstall hello-again --> removes everything as expected.
  7. state exec main --> errors saying that main was not found.

Please note this is an "extreme" scenario. In all likelihood, artifacts providing the same file will provide the same bits, so the contents will not matter. The file merely needs to exist. Therefore, this PR effectively does reference counting and will not completely remove a file until no more artifacts reference it.

…from the existing artifact after the other was undeployed/uninstalled.
@mitchell-as mitchell-as changed the title If two artifacts provide the same file, re-link or re-copy that file from the existing artifact after the other was undeployed/uninstalled. If two artifacts provide the same file, re-link or re-copy that file from the artifact left after the other was undeployed/uninstalled. Aug 20, 2024
@mitchell-as
Copy link
Contributor Author

Test failures are the usual timeouts and unrelated to this PR.

@mitchell-as
Copy link
Contributor Author

This is a first attempt. I realize this PR may go through a lot of churn.

@mitchell-as mitchell-as requested a review from Naatan August 20, 2024 22:04
@mitchell-as mitchell-as marked this pull request as ready for review August 20, 2024 22:04
pkg/runtime/depot.go Outdated Show resolved Hide resolved
pkg/runtime/depot.go Outdated Show resolved Hide resolved
pkg/runtime/depot.go Outdated Show resolved Hide resolved
pkg/runtime/depot.go Outdated Show resolved Hide resolved
pkg/runtime/depot.go Outdated Show resolved Hide resolved
pkg/runtime/depot.go Outdated Show resolved Hide resolved
newSrc := filepath.Join(d.Path(artifactId), deployment.InstallDir, relativeDeployedFile)
logging.Debug("More than one artifact provides '%s'", relativeDeployedFile)
logging.Debug("Will relink %s to %s", deployedFile, newSrc)
relink[deployedFile] = newSrc
Copy link
Member

Choose a reason for hiding this comment

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

Should probably break here. What if we have three artifacts linking to the same file? We still want to address the first one encountered.

Copy link
Contributor Author

@mitchell-as mitchell-as Aug 21, 2024

Choose a reason for hiding this comment

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

I don't see the point of this. Deployment iteration is not ordered, so we cannot make any sort of guarantee which of 2 remaining artifacts will get picked.

Furthermore, we'd have to break out of two for loops, not one, so that would either require a goto or refactor to use functions. I don't think it's worth it since we cannot make the guarantee mentioned earlier.

Let me know if you feel strongly about this. "Should probably" didn't seem too strong to me :)

Copy link
Member

Choose a reason for hiding this comment

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

Not being able to make a guarantee is already the reality we live in now. That is a problem for another day that we cannot address in this story. All we can address is that as long as there are artifacts still targeting a file, that file should exist. And one of them will arbitrarily win the race.

The main reason I brought this up is because as currently written we would remove and then link the file again here:

https://github.com/ActiveState/cli/pull/3455/files#diff-e57fe7a86f0cf670f9bb15dec637e18669380299ce1d661b3872f4e822c65bf2R299

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I added a goto to break out of 3 for loops.

@mitchell-as mitchell-as requested a review from Naatan August 21, 2024 21:35
Copy link
Member

@Naatan Naatan left a comment

Choose a reason for hiding this comment

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

Changes so far are looking good to me! Please see my responses to your prior comments.

We no longer have to avoid removing files, which could have removed needed directories.
@mitchell-as mitchell-as requested a review from Naatan August 22, 2024 15:51
Naatan
Naatan previously approved these changes Aug 22, 2024
Copy link
Member

@Naatan Naatan left a comment

Choose a reason for hiding this comment

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

Looks good! I have two minor nits, up to you if you address those.

Comment on lines 65 to 69
if destDir := filepath.Dir(dest); !fileutils.DirExists(destDir) {
if err := os.MkdirAll(destDir, 0755); err != nil {
return errs.Wrap(err, "could not create directory %s", destDir)
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Nit: You could simplify this with fileutils.MkdirUnlessExists().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay. I also found a case where we can use fileutils.Mkdir() instead of os.Mkdir() with a magic number.

@@ -355,10 +345,12 @@ func (d *depot) getSharedFilesToRedeploy(id strfmt.UUID, deploy deployment, path
logging.Debug("More than one artifact provides '%s'", relativeDeployedFile)
logging.Debug("Will redeploy '%s' to '%s'", newSrc, deployedFile)
redeploy[deployedFile] = newSrc
goto nextDeployedFile
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Would you mind using an anonymous function or a var to break out of the outer loop?

This might be my own personal pet peeve, but I find the goto statement to be an eyesore. I've never encountered a scenario where this problem cannot be solved in a (in my opinion) cleaner way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Three consecutive

if fileFound {
  break
}

looked hideous, so I tried an anonymous function. Hopefully that passes your filter :)

@mitchell-as mitchell-as reopened this Aug 22, 2024
@mitchell-as mitchell-as merged commit cc37a2a into version/0-46-0-RC1 Aug 22, 2024
12 of 13 checks passed
@mitchell-as mitchell-as deleted the mitchell/dx-2913 branch August 22, 2024 18:24
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