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

Properly upgrade Casks with version :latest #3492

Merged
merged 11 commits into from
Nov 29, 2017
Merged

Properly upgrade Casks with version :latest #3492

merged 11 commits into from
Nov 29, 2017

Conversation

amyspark
Copy link
Contributor

@amyspark amyspark commented Nov 28, 2017

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew tests with your changes locally?

When I proposed #3396, I forgot to test if the upgrade process worked for version :latest Casks.
Obviously, this came back to bite me 😢

In this initial state, I've submitted a test to summarize the issue. The missing part would be to tamper with staged_path if version :latest and use a randomized? path, but I'd like to request your comments on the best way to do it.

This pull request, once finished, fixes Homebrew/homebrew-cask#41373.

Thanks for your comments!

/cc @MikeMcQuaid @vitorgalvao @reitermarkus

@reitermarkus
Copy link
Member

Obviously, this came back to bite me 😢

No worries, there had to be something. 😜

and use a randomized? path

brew reinstall appends .reinstall to the Keg path: https://github.com/Homebrew/brew/blob/master/Library/Homebrew/cmd/reinstall.rb#L74-L76

I'd suggest to just move staged_path to "#{staged_path}.backup" (or .upgrading), and either remove it after the upgrade, or move it back if the upgrade fails.

@reitermarkus reitermarkus added the cask Homebrew Cask label Nov 28, 2017
@@ -420,6 +436,14 @@ def zap
purge_caskroom_path
end

def backup_path(path)
Pathname.new "#{path}.upgrading" unless path.nil?
Copy link
Member

Choose a reason for hiding this comment

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

When would path be nil?

Copy link
Member

Choose a reason for hiding this comment

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

Also, since this is only used for staged_path, you could make this take no arguments and just return Pathname("#{@cask.staged_path}.upgrading").

Copy link
Contributor Author

Choose a reason for hiding this comment

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

path should never be nil, but I wanted to preserve the semantics of gain_permissions_remove(staged_path) if !staged_path.nil? && staged_path.exist?.

@@ -378,10 +378,26 @@ def start_upgrade

disable_accessibility_access
uninstall_artifacts
backup if version_is_latest?
Copy link
Member

Choose a reason for hiding this comment

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

Let's always create a backup, not just when version_is_latest?.

Copy link
Contributor Author

@amyspark amyspark Nov 28, 2017

Choose a reason for hiding this comment

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

If we always create a backup, we'll need a way to know if this is the new or old cask when purge_versioned_files. Otherwise, it will leave a dangling, empty folder if the upgrade fails (see the test "restores the old Cask if the upgrade failed" in upgrade_spec.rb).
Would another variable e.g. old_cask, new_cask instead of upgrade work for you?

Copy link
Member

Choose a reason for hiding this comment

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

Isn't start_upgrade only called on the old cask?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I took advantage of that; see next commit.

(and if doing so, correctly set the staged_path when purging it)
if backed_up?
Pathname.new "#{@cask.staged_path}.upgrading"
else
@cask.staged_path
Copy link
Member

Choose a reason for hiding this comment

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

I think this is really hard to follow. The only reason for this is purge_versioned_files using it. I'd suggest making two specialised versions of purge_versioned_files, one normal one, and one for the upgrade? case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll do it that way, and then factor out the whole metadata handling (to avoid code duplication).

Avoid using variables altogether; fork out the purge into two
specialized + one common function
if @cask.metadata_versioned_path.respond_to?(:children) &&
@cask.metadata_versioned_path.exist?
@cask.metadata_versioned_path.exist? &&
!(upgrade? && version_is_latest?)
Copy link
Member

Choose a reason for hiding this comment

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

Do we still need version_is_latest? now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the backup mechanism doesn't involve the Cask's metadata; if the version is latest, deleting this line will make purge_metadata "uninstall" the Cask while leaving all artifacts in place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On second thoughts, I'll just go ahead with two fully separate methods and get rid of that line.

def gain_permissions_remove(path)
Utils.gain_permissions_remove(path, command: @command)
end

def purge_backed_versioned_files
Copy link
Member

Choose a reason for hiding this comment

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

purge_backed_up_versioned_files

Pathname.new "#{@cask.metadata_versioned_path}.upgrading"
end

def version_is_latest?
Copy link
Member

Choose a reason for hiding this comment

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

This can now be removed.

end
end
backup_metadata_path.rmdir_if_possible
@cask.metadata_master_container_path.rmdir_if_possible unless upgrade?
Copy link
Member

Choose a reason for hiding this comment

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

The unless upgrade? here doesn't make sense, because this method is only called when upgrading.

@@ -31,7 +31,7 @@ def initialize(cask, command: SystemCommand, force: false, skip_cask_deps: false
@upgrade = upgrade
end

attr_predicate :binaries?, :force?, :skip_cask_deps?, :require_sha?, :upgrade?, :verbose?
attr_predicate :binaries?, :force?, :skip_cask_deps?, :require_sha?, :upgrade?, :verbose?, :backed_up?
Copy link
Member

Choose a reason for hiding this comment

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

This is not needed anymore.

@@ -71,7 +71,7 @@ def move_back(skip: false, force: false, command: nil, **options)
command.run("/bin/mv", args: [target, source], sudo: true)
end

add_altname_metadata(target, source.basename, command: command)
add_altname_metadata(source, target.basename, command: command)
Copy link
Member

Choose a reason for hiding this comment

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

Remove this completely. We don‘t need to add this when moving it back, actually.


# Homebrew-Cask metadata
if backup_metadata_path.respond_to?(:children) &&
backup_metadata_path.exist? &&
Copy link
Member

Choose a reason for hiding this comment

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

The && shouldn‘t be here.

Copy link
Member

Choose a reason for hiding this comment

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

The whole condition here could probably just be backup_metadata_path.directory?.

Leftover && and remove xattr "copy"
@reitermarkus
Copy link
Member

reitermarkus commented Nov 29, 2017

I think you missed this comment by a minute: #3492 (comment)

@amyspark
Copy link
Contributor Author

Yep, I wasn't using my inbox to keep up with comments. Thanks for the heads up @reitermarkus.

@reitermarkus reitermarkus merged commit 3f7e63a into Homebrew:master Nov 29, 2017
@reitermarkus
Copy link
Member

Thanks again, @amyspark! 👍

@amyspark amyspark deleted the fix-latest-casks branch November 29, 2017 14:37
@Homebrew Homebrew locked and limited conversation to collaborators May 4, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cask Homebrew Cask
Projects
None yet
Development

Successfully merging this pull request may close these issues.

brew cask upgrade fails for latest Casks.
2 participants