Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
brew
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to JiHu GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
KMSCAKKSCFKA AKFACAMADCAS
brew
Commits
832c5875
Commit
832c5875
authored
9 years ago
by
Vlad Shablinsky
Committed by
Mike McQuaid
9 years ago
Browse files
Options
Downloads
Patches
Plain Diff
add migrator class for migrating renamed formulae
parent
556ab3bc
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
Library/Homebrew/migrator.rb
+303
-0
303 additions, 0 deletions
Library/Homebrew/migrator.rb
with
303 additions
and
0 deletions
Library/Homebrew/migrator.rb
0 → 100644
+
303
−
0
View file @
832c5875
require
"formula"
require
"keg"
require
"tab"
require
"tap_migrations"
class
Migrator
class
MigratorNoOldnameError
<
RuntimeError
def
initialize
(
formula
)
super
"
#{
formula
.
name
}
doesn't replace any formula."
end
end
class
MigratorNoOldpathError
<
RuntimeError
def
initialize
(
formula
)
super
"
#{
HOMEBREW_CELLAR
/
formula
.
oldname
}
doesn't exist."
end
end
class
MigratorDifferentTapsError
<
RuntimeError
def
initialize
(
formula
,
tap
)
if
tap
.
nil?
super
<<-
EOS
.
undent
#{
formula
.
name
}
from
#{
formula
.
tap
}
is given, but old name
#{
formula
.
oldname
}
wasn't installed from taps or core formulae
You can try `brew migrate --force
#{
formula
.
oldname
}
`.
EOS
else
user
,
repo
=
tap
.
split
(
"/"
)
repo
.
sub!
(
"homebrew-"
,
""
)
name
=
"fully-qualified
#{
user
}
/
#{
repo
}
/
#{
formula
.
oldname
}
"
name
=
formula
.
oldname
if
tap
==
"Homebrew/homebrew"
super
<<-
EOS
.
undent
#{
formula
.
name
}
from
#{
formula
.
tap
}
is given, but old name
#{
formula
.
oldname
}
was installed from
#{
tap
}
Please try to use
#{
name
}
to refer the formula
EOS
end
end
end
attr_reader
:formula
attr_reader
:oldname
,
:oldpath
,
:old_pin_record
,
:old_opt_record
attr_reader
:old_linked_keg_record
,
:oldkeg
,
:old_tabs
,
:old_tap
attr_reader
:newname
,
:newpath
,
:new_pin_record
attr_reader
:old_pin_link_record
def
initialize
(
formula
)
@oldname
=
formula
.
oldname
@newname
=
formula
.
name
raise
MigratorNoOldnameError
.
new
(
formula
)
unless
oldname
@formula
=
formula
@oldpath
=
HOMEBREW_CELLAR
/
formula
.
oldname
raise
MigratorNoOldpathError
.
new
(
formula
)
unless
oldpath
.
exist?
@old_tabs
=
oldpath
.
subdirs
.
each
.
map
{
|
d
|
Tab
.
for_keg
(
Keg
.
new
(
d
))
}
@old_tap
=
old_tabs
.
first
.
tap
raise
MigratorDifferentTapsError
.
new
(
formula
,
old_tap
)
unless
from_same_taps?
@newpath
=
HOMEBREW_CELLAR
/
formula
.
name
if
@oldkeg
=
get_linked_oldkeg
@old_linked_keg_record
=
oldkeg
.
linked_keg_record
if
oldkeg
.
linked?
@old_opt_record
=
oldkeg
.
opt_record
if
oldkeg
.
optlinked?
end
@old_pin_record
=
HOMEBREW_LIBRARY
/
"PinnedKegs"
/
oldname
@new_pin_record
=
HOMEBREW_LIBRARY
/
"PinnedKegs"
/
newname
@pinned
=
old_pin_record
.
symlink?
@old_pin_link_record
=
old_pin_record
.
readlink
if
@pinned
end
# Fix INSTALL_RECEIPTS for tap-migrated formula.
def
fix_tabs
old_tabs
.
each
do
|
tab
|
tab
.
source
[
"tap"
]
=
formula
.
tap
tab
.
write
end
end
def
from_same_taps?
if
old_tap
==
nil
&&
formula
.
core_formula?
&&
ARGV
.
force?
true
elsif
formula
.
tap
==
old_tap
true
# Homebrew didn't use to update tabs while performing tap-migrations,
# so there can be INSTALL_RECEIPT's containing wrong information about
# tap (tap is Homebrew/homebrew if installed formula migrates to a tap), so
# we check if there is an entry about oldname migrated to tap and if
# newname's tap is the same as tap to which oldname migrated, then we
# can perform migrations and the taps for oldname and newname are the same.
elsif
TAP_MIGRATIONS
&&
(
rec
=
TAP_MIGRATIONS
[
formula
.
oldname
])
\
&&
rec
==
formula
.
tap
.
sub
(
"homebrew-"
,
""
)
fix_tabs
true
elsif
formula
.
tap
false
end
end
def
get_linked_oldkeg
kegs
=
oldpath
.
subdirs
.
map
{
|
d
|
Keg
.
new
(
d
)
}
kegs
.
detect
(
&
:linked?
)
||
kegs
.
detect
(
&
:optlinked?
)
end
def
pinned?
@pinned
end
def
oldkeg_linked?
!!
oldkeg
end
def
migrate
if
newpath
.
exist?
onoe
"
#{
newpath
}
already exists; remove it manually and run brew migrate
#{
oldname
}
."
return
end
begin
oh1
"Migrating
#{
Tty
.
green
}#{
oldname
}#{
Tty
.
white
}
to
#{
Tty
.
green
}#{
newname
}#{
Tty
.
reset
}
"
unlink_oldname
move_to_new_directory
repin
link_newname
link_oldname_opt
link_oldname_cellar
update_tabs
rescue
Interrupt
ignore_interrupts
{
backup_oldname
}
rescue
Exception
=>
e
onoe
"error occured while migrating."
puts
e
if
ARGV
.
debug?
puts
"Backuping..."
ignore_interrupts
{
backup_oldname
}
end
end
# move everything from Cellar/oldname to Cellar/newname
def
move_to_new_directory
puts
"Moving to:
#{
newpath
}
"
FileUtils
.
mv
(
oldpath
,
newpath
)
end
def
repin
if
pinned?
# old_pin_record is a relative symlink and when we try to to read it
# from <dir> we actually try to find file
# <dir>/../<...>/../Cellar/name/version.
# To repin formula we need to update the link thus that it points to
# the right directory.
# NOTE: old_pin_record.realpath.sub(oldname, newname) is unacceptable
# here, because it resolves every symlink for old_pin_record and then
# substitutes oldname with newname. It breaks things like
# Pathname#make_relative_symlink, where Pathname#relative_path_from
# is used to find relative path from source to destination parent and
# it assumes no symlinks.
src_oldname
=
old_pin_record
.
dirname
.
join
(
old_pin_link_record
).
expand_path
new_pin_record
.
make_relative_symlink
(
src_oldname
.
sub
(
oldname
,
newname
))
old_pin_record
.
delete
end
end
def
unlink_oldname
oh1
"Unlinking
#{
Tty
.
green
}#{
oldname
}#{
Tty
.
reset
}
"
oldpath
.
subdirs
.
each
do
|
d
|
keg
=
Keg
.
new
(
d
)
keg
.
unlink
end
end
def
link_newname
oh1
"Linking
#{
Tty
.
green
}#{
newname
}#{
Tty
.
reset
}
"
keg
=
Keg
.
new
(
formula
.
installed_prefix
)
if
formula
.
keg_only?
begin
keg
.
optlink
rescue
Keg
::
LinkError
=>
e
onoe
"Failed to create
#{
formula
.
opt_prefix
}
"
puts
e
raise
end
return
end
keg
.
remove_linked_keg_record
if
keg
.
linked?
begin
keg
.
link
rescue
Keg
::
ConflictError
=>
e
onoe
"Error while executing `brew link` step on
#{
newname
}
"
puts
e
puts
puts
"Possible conflicting files are:"
mode
=
OpenStruct
.
new
(
:dry_run
=>
true
,
:overwrite
=>
true
)
keg
.
link
(
mode
)
raise
rescue
Keg
::
LinkError
=>
e
onoe
"Error while linking"
puts
e
puts
puts
"You can try again using:"
puts
" brew link
#{
formula
.
name
}
"
rescue
Exception
=>
e
onoe
"An unexpected error occurred during linking"
puts
e
puts
e
.
backtrace
ignore_interrupts
{
keg
.
unlink
}
raise
e
end
end
# Link keg to opt if it was linked before migrating.
def
link_oldname_opt
if
old_opt_record
old_opt_record
.
delete
if
old_opt_record
.
symlink?
||
old_opt_record
.
exist?
old_opt_record
.
make_relative_symlink
(
formula
.
installed_prefix
)
end
end
# After migtaion every INSTALL_RECEIPT.json has wrong path to the formula
# so we must update INSTALL_RECEIPTs
def
update_tabs
new_tabs
=
newpath
.
subdirs
.
map
{
|
d
|
Tab
.
for_keg
(
Keg
.
new
(
d
))
}
new_tabs
.
each
do
|
tab
|
tab
.
source
[
"path"
]
=
formula
.
path
.
to_s
if
tab
.
source
[
"path"
]
tab
.
write
end
end
# Remove opt/oldname link if it belongs to newname.
def
unlink_oldname_opt
return
unless
old_opt_record
if
old_opt_record
.
symlink?
&&
formula
.
installed_prefix
.
exist?
\
&&
formula
.
installed_prefix
.
realpath
==
old_opt_record
.
realpath
old_opt_record
.
unlink
old_opt_record
.
parent
.
rmdir_if_possible
end
end
# Remove oldpath if it exists
def
link_oldname_cellar
oldpath
.
delete
if
oldpath
.
symlink?
||
oldpath
.
exist?
oldpath
.
make_relative_symlink
(
formula
.
rack
)
end
# Remove Cellar/oldname link if it belongs to newname.
def
unlink_oldname_cellar
if
(
oldpath
.
symlink?
&&
!
oldpath
.
exist?
)
||
(
oldpath
.
symlink?
\
&&
formula
.
rack
.
exist?
&&
formula
.
rack
.
realpath
==
oldpath
.
realpath
)
oldpath
.
unlink
end
end
# Backup everything if errors occured while migrating.
def
backup_oldname
unlink_oldname_opt
unlink_oldname_cellar
backup_oldname_cellar
backup_old_tabs
if
pinned?
&&
!
old_pin_record
.
symlink?
src_oldname
=
old_pin_record
.
dirname
.
join
(
old_pin_link_record
).
expand_path
old_pin_record
.
make_relative_symlink
(
src_oldname
)
new_pin_record
.
delete
end
if
newpath
.
exist?
newpath
.
subdirs
.
each
do
|
d
|
newname_keg
=
Keg
.
new
(
d
)
newname_keg
.
unlink
newname_keg
.
uninstall
end
end
if
oldkeg_linked?
begin
# The keg used to be linked and when we backup everything we restore
# Cellar/oldname, the target also gets restored, so we are able to
# create a keg using its old path
keg
=
Keg
.
new
(
Pathname
.
new
(
oldkeg
.
to_s
))
keg
.
link
rescue
Keg
::
LinkError
keg
.
unlink
raise
rescue
Keg
::
AlreadyLinkedError
keg
.
unlink
retry
end
end
end
def
backup_oldname_cellar
unless
oldpath
.
exist?
FileUtils
.
mv
(
newpath
,
oldpath
)
end
end
def
backup_old_tabs
old_tabs
.
each
(
&
:write
)
end
end
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment