diff options
author | nagachika <nagachika@ruby-lang.org> | 2022-10-21 14:54:55 +0900 |
---|---|---|
committer | nagachika <nagachika@ruby-lang.org> | 2022-10-21 14:54:55 +0900 |
commit | d8c232935ea5920fd8d023db02b9443488da7252 (patch) | |
tree | ffcced7c3ad5efc9fa6c102ec8b39e70c0fb5673 /tool | |
parent | c5a0856b4b34ecd2f5be070d454dbd3fc25d9529 (diff) |
merge revision(s) 78d2be69b500e4552e0e75fdefd26606a0506009:
Move copying/linking extra files to Makefile so removed by `clean`
---
ext/extmk.rb | 81 ++++++++++++++++++++++++-----------------
tool/ln_sr.rb | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 161 insertions(+), 33 deletions(-)
create mode 100755 tool/ln_sr.rb
Diffstat (limited to 'tool')
-rw-r--r-- | tool/ln_sr.rb | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/tool/ln_sr.rb b/tool/ln_sr.rb new file mode 100644 index 0000000000..1199263e85 --- /dev/null +++ b/tool/ln_sr.rb @@ -0,0 +1,113 @@ +#!/usr/bin/ruby + +until ARGV.empty? + case ARGV[0] + when '-n' + noop = true + when '-f' + force = true + else + break + end + ARGV.shift +end + +unless ARGV.size == 2 + abort "usage: #{$0} src destdir" +end +src, dest = ARGV + +require 'fileutils' + +include FileUtils +unless respond_to?(:ln_sr) + def ln_sr(src, dest, force: nil, noop: nil, verbose: nil) + dest = File.path(dest) + srcs = Array.try_convert(src) || [src] + link = proc do |s, target_directory = true| + s = File.path(s) + if fu_starting_path?(s) + srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s))) + else + srcdirs = fu_clean_components(*fu_split_path(s)) + end + destdirs = fu_split_path(File.realdirpath(dest)) + destdirs.pop unless target_directory + base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs) + while srcdirs.first&. == ".." and base.last and !fu_starting_path?(base.last) + srcdirs.shift + base.pop + end + s = File.join(*base, *srcdirs) + d = target_directory ? File.join(dest, File.basename(s)) : dest + fu_output_message "ln -s#{force ? 'f' : ''} #{s} #{d}" if verbose + next if noop + remove_file d, true if force + File.symlink s, d + end + case srcs.size + when 0 + when 1 + link[srcs[0], File.directory?(dest)] + else + srcs.each(&link) + end + end + + def fu_split_path(path) + path = File.path(path) + list = [] + until (parent, base = File.split(path); parent == path or parent == ".") + list << base + path = parent + end + list << path + list.reverse! + end + + def fu_relative_components_from(target, base) #:nodoc: + i = 0 + while target[i]&.== base[i] + i += 1 + end + Array.new(base.size-i, '..').concat(target[i..-1]) + end + + def fu_clean_components(*comp) + comp.shift while comp.first == "." + return comp if comp.empty? + clean = [comp.shift] + path = File.join(*clean, "") # ending with File::SEPARATOR + while c = comp.shift + if c == ".." and clean.last != ".." and !(fu_have_symlink? && File.symlink?(path)) + clean.pop + path.chomp!(%r((?<=\A|/)[^/]+/\z), "") + else + clean << c + path << c << "/" + end + end + clean + end + + if fu_windows? + def fu_starting_path?(path) + path&.start_with?(%r(\w:|/)) + end + else + def fu_starting_path?(path) + path&.start_with?("/") + end + end +end + +if File.respond_to?(:symlink) + begin + ln_sr(src, dest, verbose: true, force: force, noop: noop) + rescue NotImplementedError, Errno::EPERM + else + exit + end +end + +cp_r(src, dest) |