2017-04-29 21:53:47 +00:00
|
|
|
|
require 'date'
|
|
|
|
|
|
2017-04-28 18:36:42 +00:00
|
|
|
|
Vagrant.configure(2) do |config|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
|
|
|
|
|
# We use Ubuntu instead of Debian because the image comes with two-way
|
|
|
|
|
# shared folder support by default.
|
2020-01-19 00:37:24 +00:00
|
|
|
|
UBUNTU = 'bento/ubuntu-16.04'
|
2017-09-30 13:23:55 +00:00
|
|
|
|
|
|
|
|
|
# The main VM is the one used for development and testing.
|
|
|
|
|
config.vm.define(:exa, primary: true) do |config|
|
2017-04-28 18:36:42 +00:00
|
|
|
|
config.vm.provider :virtualbox do |v|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
v.name = 'exa'
|
2020-01-19 00:37:24 +00:00
|
|
|
|
v.memory = 2048
|
|
|
|
|
v.cpus = 2
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
config.vm.provider :vmware_desktop do |v|
|
|
|
|
|
v.vmx['memsize'] = '2048'
|
|
|
|
|
v.vmx['numvcpus'] = '2'
|
2016-10-07 18:31:03 +00:00
|
|
|
|
end
|
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
config.vm.box = UBUNTU
|
|
|
|
|
config.vm.hostname = 'exa'
|
2017-05-06 18:38:34 +00:00
|
|
|
|
|
2017-04-28 18:36:42 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
# Make sure we know the VM image’s default user name. The ‘cassowary’ user
|
|
|
|
|
# (specified later) is used for most of the test *output*, but we still
|
|
|
|
|
# need to know where the ‘target’ and ‘.cargo’ directories go.
|
2018-09-26 20:25:50 +00:00
|
|
|
|
developer = 'vagrant'
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2017-04-30 10:06:52 +00:00
|
|
|
|
# Install the dependencies needed for exa to build, as quietly as
|
|
|
|
|
# apt can do.
|
2017-05-06 19:34:59 +00:00
|
|
|
|
config.vm.provision :shell, privileged: true, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
apt-get update
|
|
|
|
|
apt-get install -qq -o=Dpkg::Use-Pty=0 -y \
|
|
|
|
|
git cmake curl attr libgit2-dev zip \
|
|
|
|
|
fish zsh bash bash-completion
|
2017-05-06 19:34:59 +00:00
|
|
|
|
EOF
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
|
|
|
|
# Guarantee that the timezone is UTC -- some of the tests
|
|
|
|
|
# depend on this (for now).
|
|
|
|
|
config.vm.provision :shell, privileged: true, inline:
|
2017-09-30 13:23:55 +00:00
|
|
|
|
%[timedatectl set-timezone UTC]
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2016-10-07 18:31:03 +00:00
|
|
|
|
# Install Rust.
|
|
|
|
|
# This is done as vagrant, not root, because it’s vagrant
|
|
|
|
|
# who actually uses it. Sent to /dev/null because the progress
|
2017-04-28 18:34:23 +00:00
|
|
|
|
# bar produces a ton of output.
|
2019-07-13 19:15:44 +00:00
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
|
|
|
|
if hash rustc &>/dev/null; then
|
|
|
|
|
echo "Rust is already installed"
|
|
|
|
|
else
|
|
|
|
|
set -xe
|
|
|
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
|
|
|
|
fi
|
|
|
|
|
EOF
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2016-10-07 18:31:03 +00:00
|
|
|
|
# Use a different ‘target’ directory on the VM than on the host.
|
|
|
|
|
# By default it just uses the one in /vagrant/target, which can
|
|
|
|
|
# cause problems if it has different permissions than the other
|
|
|
|
|
# directories, or contains object files compiled for the host.
|
2017-08-19 16:59:52 +00:00
|
|
|
|
config.vm.provision :shell, privileged: true, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/#{developer}/.cargo/bin"' > /etc/environment
|
|
|
|
|
echo 'CARGO_TARGET_DIR="/home/#{developer}/target"' >> /etc/environment
|
2017-05-06 19:34:59 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
2017-08-19 16:59:52 +00:00
|
|
|
|
# Create a variety of misc scripts.
|
2017-05-06 19:34:59 +00:00
|
|
|
|
config.vm.provision :shell, privileged: true, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
2017-05-07 19:25:53 +00:00
|
|
|
|
|
2017-10-02 08:22:50 +00:00
|
|
|
|
ln -sf /vagrant/devtools/dev-run-debug.sh /usr/bin/exa
|
|
|
|
|
ln -sf /vagrant/devtools/dev-run-release.sh /usr/bin/rexa
|
2017-08-26 14:13:19 +00:00
|
|
|
|
|
2017-10-02 08:22:50 +00:00
|
|
|
|
echo -e "#!/bin/sh\ncargo build --manifest-path /vagrant/Cargo.toml \\$@" > /usr/bin/build-exa
|
2017-09-30 13:23:55 +00:00
|
|
|
|
ln -sf /usr/bin/build-exa /usr/bin/b
|
2017-08-26 14:13:19 +00:00
|
|
|
|
|
2017-10-02 08:22:50 +00:00
|
|
|
|
echo -e "#!/bin/sh\ncargo test --manifest-path /vagrant/Cargo.toml --lib \\$@ -- --quiet" > /usr/bin/test-exa
|
2017-09-30 13:23:55 +00:00
|
|
|
|
ln -sf /usr/bin/test-exa /usr/bin/t
|
2017-08-26 14:13:19 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo -e "#!/bin/sh\n/vagrant/xtests/run.sh" > /usr/bin/run-xtests
|
|
|
|
|
ln -sf /usr/bin/run-xtests /usr/bin/x
|
2017-08-19 16:59:52 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo -e "#!/bin/sh\nbuild-exa && test-exa && run-xtests" > /usr/bin/compile-exa
|
|
|
|
|
ln -sf /usr/bin/compile-exa /usr/bin/c
|
2017-08-20 17:19:58 +00:00
|
|
|
|
|
2017-10-08 19:44:34 +00:00
|
|
|
|
echo -e "#!/bin/sh\nbash /vagrant/devtools/dev-package-for-linux.sh \\$@" > /usr/bin/package-exa
|
|
|
|
|
echo -e "#!/bin/sh\ncat /etc/motd" > /usr/bin/halp
|
2017-08-26 14:13:19 +00:00
|
|
|
|
|
2017-10-02 08:26:39 +00:00
|
|
|
|
chmod +x /usr/bin/{exa,rexa,b,t,x,c,build-exa,test-exa,run-xtests,compile-exa,package-exa,halp}
|
2017-08-19 16:59:52 +00:00
|
|
|
|
EOF
|
2017-08-26 14:13:19 +00:00
|
|
|
|
|
|
|
|
|
|
2017-08-20 19:04:59 +00:00
|
|
|
|
# This fix is applied by changing the VM rather than changing the
|
|
|
|
|
# Cargo.toml file so it works for everyone because it’s such a niche
|
|
|
|
|
# build issue, it’s not worth specifying a non-crates.io dependency
|
|
|
|
|
# and losing the ability to `cargo publish` the exa crate there!
|
|
|
|
|
# It also isolates the hackiness to the one place I can test it
|
|
|
|
|
# actually works.
|
2017-08-19 16:59:52 +00:00
|
|
|
|
|
|
|
|
|
|
2017-10-01 07:49:45 +00:00
|
|
|
|
# Configure the welcoming text that gets shown.
|
2017-08-19 16:59:52 +00:00
|
|
|
|
config.vm.provision :shell, privileged: true, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
rm -f /etc/update-motd.d/*
|
|
|
|
|
|
2017-10-01 07:49:45 +00:00
|
|
|
|
# Capture the help text so it gets displayed first
|
|
|
|
|
bash /vagrant/devtools/dev-help.sh > /etc/motd
|
|
|
|
|
|
|
|
|
|
# Tell bash to execute a bunch of stuff when a session starts
|
2018-09-26 20:25:50 +00:00
|
|
|
|
echo "source /vagrant/devtools/dev-bash.sh" > /home/#{developer}/.bash_profile
|
2019-07-13 19:15:44 +00:00
|
|
|
|
chown #{developer} /home/#{developer}/.bash_profile
|
2017-09-30 13:23:55 +00:00
|
|
|
|
|
|
|
|
|
# Disable last login date in sshd
|
|
|
|
|
sed -i '/PrintLastLog yes/c\PrintLastLog no' /etc/ssh/sshd_config
|
|
|
|
|
systemctl restart sshd
|
2017-05-06 18:07:29 +00:00
|
|
|
|
EOF
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
|
|
|
|
|
2017-05-06 19:34:59 +00:00
|
|
|
|
# Link the completion files so they’re “installed”.
|
|
|
|
|
config.vm.provision :shell, privileged: true, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
2017-05-07 19:25:53 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
test -h /etc/bash_completion.d/exa \
|
|
|
|
|
|| ln -s /vagrant/contrib/completions.bash /etc/bash_completion.d/exa
|
2017-05-06 20:56:40 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
test -h /usr/share/zsh/vendor-completions/_exa \
|
|
|
|
|
|| ln -s /vagrant/contrib/completions.zsh /usr/share/zsh/vendor-completions/_exa
|
2017-05-06 19:50:24 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
test -h /usr/share/fish/completions/exa.fish \
|
|
|
|
|
|| ln -s /vagrant/contrib/completions.fish /usr/share/fish/completions/exa.fish
|
2017-05-06 19:34:59 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
# We create two users that own the test files.
|
2017-05-06 18:38:34 +00:00
|
|
|
|
# The first one just owns the ordinary ones, because we don’t want the
|
|
|
|
|
# test outputs to depend on “vagrant” or “ubuntu” existing.
|
2017-04-28 18:34:23 +00:00
|
|
|
|
user = "cassowary"
|
|
|
|
|
config.vm.provision :shell, privileged: true, inline:
|
2017-09-30 13:23:55 +00:00
|
|
|
|
%[id -u #{user} &>/dev/null || useradd #{user}]
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
# The second one has a long name, to test that the file owner column
|
|
|
|
|
# widens correctly. The benefit of Vagrant is that we don’t need to
|
|
|
|
|
# set this up on the *actual* system!
|
2016-10-07 18:31:03 +00:00
|
|
|
|
longuser = "antidisestablishmentarienism"
|
|
|
|
|
config.vm.provision :shell, privileged: true, inline:
|
2017-09-30 13:23:55 +00:00
|
|
|
|
%[id -u #{longuser} &>/dev/null || useradd #{longuser}]
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2017-04-28 18:26:57 +00:00
|
|
|
|
# Because the timestamps are formatted differently depending on whether
|
|
|
|
|
# they’re in the current year or not (see `details.rs`), we have to make
|
|
|
|
|
# sure that the files are created in the current year, so they get shown
|
|
|
|
|
# in the format we expect.
|
|
|
|
|
current_year = Date.today.year
|
|
|
|
|
some_date = "#{current_year}01011234.56" # 1st January, 12:34:56
|
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
|
|
|
|
# We also need an UID and a GID that are guaranteed to not exist, to
|
|
|
|
|
# test what happen when they don’t.
|
2016-10-07 18:31:03 +00:00
|
|
|
|
invalid_uid = 666
|
|
|
|
|
invalid_gid = 616
|
|
|
|
|
|
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
# Delete old testcases if they exist already, then create a
|
|
|
|
|
# directory to house new ones.
|
|
|
|
|
test_dir = "/testcases"
|
|
|
|
|
config.vm.provision :shell, privileged: true, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
rm -rfv #{test_dir}
|
|
|
|
|
mkdir #{test_dir}
|
|
|
|
|
chmod 777 #{test_dir}
|
2017-04-28 18:34:23 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
|
|
|
|
# Awkward file size testcases.
|
2017-04-28 18:34:23 +00:00
|
|
|
|
# This needs sudo to set the files’ users at the very end.
|
2016-10-07 18:31:03 +00:00
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/files"
|
|
|
|
|
for i in {1..13}; do
|
|
|
|
|
fallocate -l "$i" "#{test_dir}/files/$i"_bytes
|
|
|
|
|
fallocate -l "$i"KiB "#{test_dir}/files/$i"_KiB
|
|
|
|
|
fallocate -l "$i"MiB "#{test_dir}/files/$i"_MiB
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
touch -t #{some_date} "#{test_dir}/files/"*
|
|
|
|
|
chmod 644 "#{test_dir}/files/"*
|
|
|
|
|
sudo chown #{user}:#{user} "#{test_dir}/files/"*
|
2016-10-07 18:31:03 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2016-10-29 18:25:07 +00:00
|
|
|
|
# File name extension testcases.
|
2017-06-29 12:57:31 +00:00
|
|
|
|
# These aren’t tested in details view, but we set timestamps on them to
|
|
|
|
|
# test that various sort options work.
|
2016-10-29 18:25:07 +00:00
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/file-names-exts"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/Makefile"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/IMAGE.PNG"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/image.svg"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/VIDEO.AVI"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/video.wmv"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/music.mp3"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/MUSIC.OGG"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/lossless.flac"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/lossless.wav"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/crypto.asc"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/crypto.signature"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/document.pdf"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/DOCUMENT.XLSX"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/COMPRESSED.ZIP"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/compressed.tar.gz"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/compressed.tgz"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/compressed.tar.xz"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/compressed.txz"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/compressed.deb"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/backup~"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/#SAVEFILE#"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/file.tmp"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch "#{test_dir}/file-names-exts/compiled.class"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/compiled.o"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/compiled.js"
|
|
|
|
|
touch "#{test_dir}/file-names-exts/compiled.coffee"
|
2016-10-29 18:25:07 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2017-05-01 11:22:57 +00:00
|
|
|
|
# File name testcases.
|
|
|
|
|
# bash really doesn’t want you to create a file with escaped characters
|
|
|
|
|
# in its name, so we have to resort to the echo builtin and touch!
|
|
|
|
|
#
|
|
|
|
|
# The double backslashes are not strictly necessary; without them, Ruby
|
|
|
|
|
# will interpolate them instead of bash, but because Vagrant prints out
|
|
|
|
|
# each command it runs, your *own* terminal will go “ding” from the alarm!
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/file-names"
|
2017-05-01 11:22:57 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo -ne "#{test_dir}/file-names/ascii: hello" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/emoji: [🆒]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/utf-8: pâté" | xargs -0 touch
|
2017-05-01 11:22:57 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo -ne "#{test_dir}/file-names/bell: [\\a]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/backspace: [\\b]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/form-feed: [\\f]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/new-line: [\\n]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/return: [\\r]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/tab: [\\t]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/vertical-tab: [\\v]" | xargs -0 touch
|
2017-05-01 11:22:57 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo -ne "#{test_dir}/file-names/escape: [\\033]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/ansi: [\\033[34mblue\\033[0m]" | xargs -0 touch
|
2017-05-01 11:22:57 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo -ne "#{test_dir}/file-names/invalid-utf8-1: [\\xFF]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/invalid-utf8-2: [\\xc3\\x28]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/invalid-utf8-3: [\\xe2\\x82\\x28]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/invalid-utf8-4: [\\xf0\\x28\\x8c\\x28]" | xargs -0 touch
|
2017-05-01 20:54:53 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo -ne "#{test_dir}/file-names/new-line-dir: [\\n]" | xargs -0 mkdir
|
|
|
|
|
echo -ne "#{test_dir}/file-names/new-line-dir: [\\n]/subfile" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/new-line-dir: [\\n]/another: [\\n]" | xargs -0 touch
|
|
|
|
|
echo -ne "#{test_dir}/file-names/new-line-dir: [\\n]/broken" | xargs -0 touch
|
2017-05-01 20:54:53 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
mkdir "#{test_dir}/file-names/links"
|
|
|
|
|
ln -s "#{test_dir}/file-names/new-line-dir"*/* "#{test_dir}/file-names/links"
|
2017-05-02 07:46:43 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo -ne "#{test_dir}/file-names/new-line-dir: [\\n]/broken" | xargs -0 rm
|
2017-05-01 11:22:57 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
2017-04-28 22:24:19 +00:00
|
|
|
|
# Special file testcases.
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/specials"
|
2017-04-28 22:24:19 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
sudo mknod "#{test_dir}/specials/block-device" b 3 60
|
|
|
|
|
sudo mknod "#{test_dir}/specials/char-device" c 14 40
|
|
|
|
|
sudo mknod "#{test_dir}/specials/named-pipe" p
|
2017-04-29 08:21:31 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
sudo touch -t #{some_date} "#{test_dir}/specials/"*
|
2017-04-28 22:24:19 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
2016-10-07 18:31:03 +00:00
|
|
|
|
# Awkward symlink testcases.
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/links"
|
|
|
|
|
|
|
|
|
|
ln -s / "#{test_dir}/links/root"
|
|
|
|
|
ln -s /usr "#{test_dir}/links/usr"
|
|
|
|
|
ln -s nowhere "#{test_dir}/links/broken"
|
|
|
|
|
ln -s /proc/1/root "#{test_dir}/links/forbidden"
|
|
|
|
|
|
|
|
|
|
touch "#{test_dir}/links/some_file"
|
|
|
|
|
ln -s "#{test_dir}/links/some_file" "#{test_dir}/links/some_file_absolute"
|
|
|
|
|
(cd "#{test_dir}/links"; ln -s "some_file" "some_file_relative")
|
|
|
|
|
(cd "#{test_dir}/links"; ln -s "." "current_dir")
|
|
|
|
|
(cd "#{test_dir}/links"; ln -s ".." "parent_dir")
|
|
|
|
|
(cd "#{test_dir}/links"; ln -s "itself" "itself")
|
2016-10-07 18:31:03 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2016-10-07 18:31:03 +00:00
|
|
|
|
# Awkward passwd testcases.
|
|
|
|
|
# sudo is needed for these because we technically aren’t a member
|
|
|
|
|
# of the groups (because they don’t exist), and chown and chgrp
|
|
|
|
|
# are smart enough to disallow it!
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/passwd"
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch -t #{some_date} "#{test_dir}/passwd/unknown-uid"
|
|
|
|
|
chmod 644 "#{test_dir}/passwd/unknown-uid"
|
|
|
|
|
sudo chown #{invalid_uid}:#{user} "#{test_dir}/passwd/unknown-uid"
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
touch -t #{some_date} "#{test_dir}/passwd/unknown-gid"
|
|
|
|
|
chmod 644 "#{test_dir}/passwd/unknown-gid"
|
|
|
|
|
sudo chown #{user}:#{invalid_gid} "#{test_dir}/passwd/unknown-gid"
|
2016-10-07 18:31:03 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2016-10-07 18:31:03 +00:00
|
|
|
|
# Awkward permission testcases.
|
2017-05-30 14:32:11 +00:00
|
|
|
|
# Differences in the way ‘chmod’ handles setting ‘setuid’ and ‘setgid’
|
|
|
|
|
# when you don’t already own the file mean that we need to use ‘sudo’
|
|
|
|
|
# to change permissions to those.
|
2016-10-07 18:31:03 +00:00
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/permissions"
|
|
|
|
|
|
|
|
|
|
mkdir "#{test_dir}/permissions/forbidden-directory"
|
|
|
|
|
chmod 000 "#{test_dir}/permissions/forbidden-directory"
|
|
|
|
|
touch -t #{some_date} "#{test_dir}/permissions/forbidden-directory"
|
|
|
|
|
sudo chown #{user}:#{user} "#{test_dir}/permissions/forbidden-directory"
|
|
|
|
|
|
|
|
|
|
for perms in 000 001 002 004 010 020 040 100 200 400 644 755 777 1000 1001 2000 2010 4000 4100 7666 7777; do
|
|
|
|
|
touch "#{test_dir}/permissions/$perms"
|
|
|
|
|
sudo chown #{user}:#{user} "#{test_dir}/permissions/$perms"
|
|
|
|
|
sudo chmod $perms "#{test_dir}/permissions/$perms"
|
|
|
|
|
sudo touch -t #{some_date} "#{test_dir}/permissions/$perms"
|
|
|
|
|
done
|
2016-10-07 18:31:03 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
2017-07-03 07:46:38 +00:00
|
|
|
|
old = '200303030000.00'
|
2017-08-06 21:25:00 +00:00
|
|
|
|
med = '200606152314.29' # the june gets used for fr_FR locale tests
|
|
|
|
|
new = '200912221038.53' # and the december for ja_JP local tests
|
2017-07-03 07:46:38 +00:00
|
|
|
|
|
|
|
|
|
# Awkward date and time testcases.
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/dates"
|
|
|
|
|
|
|
|
|
|
# there's no way to touch the created date of a file...
|
|
|
|
|
# so we have to do this the old-fashioned way!
|
|
|
|
|
# (and make sure these don't actually get listed)
|
|
|
|
|
touch -t #{old} "#{test_dir}/dates/peach"; sleep 1
|
|
|
|
|
touch -t #{med} "#{test_dir}/dates/plum"; sleep 1
|
|
|
|
|
touch -t #{new} "#{test_dir}/dates/pear"
|
|
|
|
|
|
|
|
|
|
# modified dates
|
|
|
|
|
touch -t #{old} -m "#{test_dir}/dates/pear"
|
|
|
|
|
touch -t #{med} -m "#{test_dir}/dates/peach"
|
|
|
|
|
touch -t #{new} -m "#{test_dir}/dates/plum"
|
|
|
|
|
|
|
|
|
|
# accessed dates
|
|
|
|
|
touch -t #{old} -a "#{test_dir}/dates/plum"
|
|
|
|
|
touch -t #{med} -a "#{test_dir}/dates/pear"
|
|
|
|
|
touch -t #{new} -a "#{test_dir}/dates/peach"
|
2017-07-05 21:07:03 +00:00
|
|
|
|
|
|
|
|
|
sudo chown #{user}:#{user} -R "#{test_dir}/dates"
|
2017-07-03 07:46:38 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
|
|
|
|
# Awkward extended attribute testcases.
|
2017-07-04 16:42:16 +00:00
|
|
|
|
# We need to test combinations of various numbers of files *and*
|
|
|
|
|
# extended attributes in directories. Turns out, the easiest way to
|
|
|
|
|
# do this is to generate all combinations of files with “one-xattr”
|
|
|
|
|
# or “two-xattrs” in their name and directories with “empty” or
|
|
|
|
|
# “one-file” in their name, then just give the right number of
|
|
|
|
|
# xattrs and children to those.
|
2016-10-07 18:31:03 +00:00
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/attributes"
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
mkdir "#{test_dir}/attributes/files"
|
|
|
|
|
touch "#{test_dir}/attributes/files/"{no-xattrs,one-xattr,two-xattrs}{,_forbidden}
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
mkdir "#{test_dir}/attributes/dirs"
|
|
|
|
|
mkdir "#{test_dir}/attributes/dirs/"{no-xattrs,one-xattr,two-xattrs}_{empty,one-file,two-files}{,_forbidden}
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
setfattr -n user.greeting -v hello "#{test_dir}/attributes"/**/*{one-xattr,two-xattrs}*
|
|
|
|
|
setfattr -n user.another_greeting -v hi "#{test_dir}/attributes"/**/*two-xattrs*
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
for dir in "#{test_dir}/attributes/dirs/"*one-file*; do
|
|
|
|
|
touch $dir/file-in-question
|
|
|
|
|
done
|
2017-07-04 16:42:16 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
for dir in "#{test_dir}/attributes/dirs/"*two-files*; do
|
|
|
|
|
touch $dir/this-file
|
|
|
|
|
touch $dir/that-file
|
|
|
|
|
done
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
find "#{test_dir}/attributes" -exec touch {} -t #{some_date} \\;
|
2016-10-07 18:31:03 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
# I want to use the following to test,
|
|
|
|
|
# but it only works on macos:
|
|
|
|
|
#chmod +a "#{user} deny readextattr" "#{test_dir}/attributes"/**/*_forbidden
|
2017-04-28 18:34:23 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
sudo chmod 000 "#{test_dir}/attributes"/**/*_forbidden
|
|
|
|
|
sudo chown #{user}:#{user} -R "#{test_dir}/attributes"
|
2016-10-07 18:31:03 +00:00
|
|
|
|
EOF
|
2017-05-07 19:25:53 +00:00
|
|
|
|
|
|
|
|
|
|
2017-05-17 08:17:12 +00:00
|
|
|
|
# A sample Git repository
|
|
|
|
|
# This uses cd because it's easier than telling Git where to go each time
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir "#{test_dir}/git"
|
|
|
|
|
cd "#{test_dir}/git"
|
|
|
|
|
git init
|
2017-05-17 08:17:12 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
mkdir edits additions moves
|
2017-05-17 08:17:12 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo "original content" | tee edits/{staged,unstaged,both}
|
|
|
|
|
echo "this file gets moved" > moves/hither
|
2017-05-17 08:17:12 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
git add edits moves
|
2018-09-26 20:25:50 +00:00
|
|
|
|
git config --global user.email "exa@exa.exa"
|
|
|
|
|
git config --global user.name "Exa Exa"
|
2017-09-30 13:23:55 +00:00
|
|
|
|
git commit -m "Automated test commit"
|
2017-05-17 08:17:12 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
echo "modifications!" | tee edits/{staged,both}
|
|
|
|
|
touch additions/{staged,edited}
|
|
|
|
|
mv moves/{hither,thither}
|
2017-05-17 08:17:12 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
git add edits moves additions
|
|
|
|
|
echo "more modifications!" | tee edits/unstaged edits/both additions/edited
|
|
|
|
|
touch additions/unstaged
|
2017-05-17 08:17:12 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
find "#{test_dir}/git" -exec touch {} -t #{some_date} \\;
|
|
|
|
|
sudo chown #{user}:#{user} -R "#{test_dir}/git"
|
2017-05-17 08:17:12 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
2017-08-28 14:10:29 +00:00
|
|
|
|
# A second Git repository
|
|
|
|
|
# for testing two at once
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
mkdir -p "#{test_dir}/git2/deeply/nested/directory"
|
|
|
|
|
cd "#{test_dir}/git2"
|
|
|
|
|
git init
|
|
|
|
|
|
|
|
|
|
touch "deeply/nested/directory/upd8d"
|
|
|
|
|
git add "deeply/nested/directory/upd8d"
|
|
|
|
|
git commit -m "Automated test commit"
|
|
|
|
|
|
|
|
|
|
echo "Now with contents" > "deeply/nested/directory/upd8d"
|
|
|
|
|
touch "deeply/nested/directory/l8st"
|
|
|
|
|
|
|
|
|
|
echo -e "target\n*.mp3" > ".gitignore"
|
|
|
|
|
mkdir "ignoreds"
|
|
|
|
|
touch "ignoreds/music.mp3"
|
|
|
|
|
touch "ignoreds/music.m4a"
|
|
|
|
|
mkdir "ignoreds/nested"
|
|
|
|
|
touch "ignoreds/nested/70s grove.mp3"
|
|
|
|
|
touch "ignoreds/nested/funky chicken.m4a"
|
|
|
|
|
|
|
|
|
|
mkdir "target"
|
|
|
|
|
touch "target/another ignored file"
|
|
|
|
|
|
|
|
|
|
mkdir "deeply/nested/repository"
|
|
|
|
|
cd "deeply/nested/repository"
|
|
|
|
|
git init
|
|
|
|
|
touch subfile
|
|
|
|
|
|
|
|
|
|
find "#{test_dir}/git2" -exec touch {} -t #{some_date} \\;
|
|
|
|
|
sudo chown #{user}:#{user} -R "#{test_dir}/git2"
|
2017-08-28 14:10:29 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
2019-09-15 14:56:58 +00:00
|
|
|
|
# A third Git repository
|
|
|
|
|
# Regression test for https://github.com/ogham/exa/issues/526
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
|
|
|
|
set -xe
|
|
|
|
|
mkdir -p "#{test_dir}/git3"
|
|
|
|
|
cd "#{test_dir}/git3"
|
|
|
|
|
git init
|
|
|
|
|
|
|
|
|
|
# Create a symbolic link pointing to a non-existing file
|
|
|
|
|
ln -s aaa/aaa/a b
|
|
|
|
|
|
|
|
|
|
find "#{test_dir}/git3" -exec touch {} -t #{some_date} \\;
|
|
|
|
|
sudo chown #{user}:#{user} -R "#{test_dir}/git3"
|
|
|
|
|
EOF
|
|
|
|
|
|
Override the names of . and ..
There was a problem when displaying . and .. in directory listings: their names would normalise to actual names! So instead of literally seeing `.`, you’d see the current directory’s name, inserted in sort order into the list of results. Obviously this is not what we want.
In unrelated news, putting `.` and `..` into the list of paths read from a directory just takes up more heap space for something that’s basically constant.
We can solve both these problems at once by moving the DotFilter to the files iterator in Dir, rather than at the Dir’s creation. Having the iterator know whether it should display `.` and `..` means it can emit those files first, and because it knows what those files really represent, it can override their file names to actually be those sequences of dots.
This is not a perfect solution: the main casualty is that a File can now be constructed with a name, some metadata, both, or neither. This is currently handled with a bunch of Options, and returns IOResult even without doing any IO operations.
But at least all the tests pass!
2017-06-28 17:41:31 +00:00
|
|
|
|
# Hidden and dot file testcases.
|
|
|
|
|
# We need to set the permissions of `.` and `..` because they actually
|
|
|
|
|
# get displayed in the output here, so this has to come last.
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
|
|
|
|
shopt -u dotglob
|
|
|
|
|
GLOBIGNORE=".:.."
|
|
|
|
|
|
|
|
|
|
mkdir "#{test_dir}/hiddens"
|
|
|
|
|
touch "#{test_dir}/hiddens/visible"
|
|
|
|
|
touch "#{test_dir}/hiddens/.hidden"
|
|
|
|
|
touch "#{test_dir}/hiddens/..extra-hidden"
|
|
|
|
|
|
|
|
|
|
# ./hiddens/
|
|
|
|
|
touch -t #{some_date} "#{test_dir}/hiddens/"*
|
|
|
|
|
chmod 644 "#{test_dir}/hiddens/"*
|
|
|
|
|
sudo chown #{user}:#{user} "#{test_dir}/hiddens/"*
|
|
|
|
|
|
|
|
|
|
# .
|
|
|
|
|
touch -t #{some_date} "#{test_dir}/hiddens"
|
|
|
|
|
chmod 755 "#{test_dir}/hiddens"
|
|
|
|
|
sudo chown #{user}:#{user} "#{test_dir}/hiddens"
|
|
|
|
|
|
|
|
|
|
# ..
|
|
|
|
|
sudo touch -t #{some_date} "#{test_dir}"
|
|
|
|
|
sudo chmod 755 "#{test_dir}"
|
|
|
|
|
sudo chown #{user}:#{user} "#{test_dir}"
|
Override the names of . and ..
There was a problem when displaying . and .. in directory listings: their names would normalise to actual names! So instead of literally seeing `.`, you’d see the current directory’s name, inserted in sort order into the list of results. Obviously this is not what we want.
In unrelated news, putting `.` and `..` into the list of paths read from a directory just takes up more heap space for something that’s basically constant.
We can solve both these problems at once by moving the DotFilter to the files iterator in Dir, rather than at the Dir’s creation. Having the iterator know whether it should display `.` and `..` means it can emit those files first, and because it knows what those files really represent, it can override their file names to actually be those sequences of dots.
This is not a perfect solution: the main casualty is that a File can now be constructed with a name, some metadata, both, or neither. This is currently handled with a bunch of Options, and returns IOResult even without doing any IO operations.
But at least all the tests pass!
2017-06-28 17:41:31 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
2017-08-06 21:25:00 +00:00
|
|
|
|
# Set up some locales
|
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
set -xe
|
2017-08-06 21:25:00 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
# uncomment these from the config file
|
|
|
|
|
sudo sed -i '/fr_FR.UTF-8/s/^# //g' /etc/locale.gen
|
|
|
|
|
sudo sed -i '/ja_JP.UTF-8/s/^# //g' /etc/locale.gen
|
|
|
|
|
sudo locale-gen
|
2017-08-06 21:25:00 +00:00
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
2017-05-07 19:25:53 +00:00
|
|
|
|
# Install kcov for test coverage
|
|
|
|
|
# This doesn’t run coverage over the xtests so it’s less useful for now
|
|
|
|
|
if ENV.key?('INSTALL_KCOV')
|
2017-09-30 13:23:55 +00:00
|
|
|
|
config.vm.provision :shell, privileged: false, inline: <<-EOF
|
|
|
|
|
set -xe
|
|
|
|
|
|
|
|
|
|
test -e ~/.cargo/bin/cargo-kcov \
|
|
|
|
|
|| cargo install cargo-kcov
|
|
|
|
|
|
|
|
|
|
sudo apt-get install -qq -o=Dpkg::Use-Pty=0 -y \
|
|
|
|
|
cmake g++ pkg-config \
|
|
|
|
|
libcurl4-openssl-dev libdw-dev binutils-dev libiberty-dev
|
|
|
|
|
|
|
|
|
|
cargo kcov --print-install-kcov-sh | sudo sh
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
end
|
2017-05-07 19:25:53 +00:00
|
|
|
|
|
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
# Remember that problem that exa had where the binary wasn’t actually
|
|
|
|
|
# self-contained? Or the problem where the Linux binary was actually the
|
|
|
|
|
# macOS binary in disguise?
|
|
|
|
|
#
|
|
|
|
|
# This is a “fresh” VM that intentionally downloads no dependencies and
|
|
|
|
|
# installs nothing so that we can check that exa still runs!
|
|
|
|
|
config.vm.define(:fresh) do |config|
|
|
|
|
|
config.vm.box = UBUNTU
|
|
|
|
|
config.vm.hostname = 'fresh'
|
2017-05-07 19:25:53 +00:00
|
|
|
|
|
2017-09-30 13:23:55 +00:00
|
|
|
|
config.vm.provider :virtualbox do |v|
|
|
|
|
|
v.name = 'exa-fresh'
|
|
|
|
|
v.memory = 384
|
|
|
|
|
v.cpus = 1
|
2017-05-07 19:25:53 +00:00
|
|
|
|
end
|
2017-10-01 10:28:23 +00:00
|
|
|
|
|
|
|
|
|
# Well, we do need *one* dependency...
|
|
|
|
|
config.vm.provision :shell, privileged: true, inline: <<-EOF
|
|
|
|
|
set -xe
|
|
|
|
|
apt-get install -qq -o=Dpkg::Use-Pty=0 -y unzip
|
|
|
|
|
EOF
|
2017-10-01 10:37:35 +00:00
|
|
|
|
|
|
|
|
|
# This thing also has its own welcoming text.
|
|
|
|
|
config.vm.provision :shell, privileged: true, inline: <<-EOF
|
|
|
|
|
rm -f /etc/update-motd.d/*
|
|
|
|
|
|
|
|
|
|
# Capture the help text so it gets displayed first
|
|
|
|
|
bash /vagrant/devtools/dev-help-testvm.sh > /etc/motd
|
|
|
|
|
|
|
|
|
|
# Disable last login date in sshd
|
|
|
|
|
sed -i '/PrintLastLog yes/c\PrintLastLog no' /etc/ssh/sshd_config
|
|
|
|
|
systemctl restart sshd
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
# Make the checker script a command.
|
|
|
|
|
config.vm.provision :shell, privileged: true, inline: <<-EOF
|
|
|
|
|
set -xe
|
|
|
|
|
echo -e "#!/bin/sh\nbash /vagrant/devtools/dev-download-and-check-release.sh \"\\$*\"" > /usr/bin/check-release
|
|
|
|
|
chmod +x /usr/bin/check-release
|
|
|
|
|
EOF
|
2017-09-30 13:23:55 +00:00
|
|
|
|
end
|
2016-10-07 18:31:03 +00:00
|
|
|
|
end
|