mirror of
https://github.com/9001/copyparty.git
synced 2026-01-13 08:12:39 -07:00
Merge branch '9001:hovudstraum' into hovudstraum
This commit is contained in:
commit
3d228d9a6e
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -43,6 +43,7 @@ scripts/docker/*.err
|
||||||
|
|
||||||
# nix build output link
|
# nix build output link
|
||||||
result
|
result
|
||||||
|
result-*
|
||||||
|
|
||||||
# IDEA config
|
# IDEA config
|
||||||
.idea/
|
.idea/
|
||||||
|
|
|
||||||
|
|
@ -2924,6 +2924,11 @@ if [cfssl](https://github.com/cloudflare/cfssl/releases/latest) is installed, co
|
||||||
* this will be a self-signed certificate so you must install your `ca.pem` into all your browsers/devices
|
* this will be a self-signed certificate so you must install your `ca.pem` into all your browsers/devices
|
||||||
* if you want to avoid the hassle of distributing certs manually, please consider using a reverse proxy
|
* if you want to avoid the hassle of distributing certs manually, please consider using a reverse proxy
|
||||||
|
|
||||||
|
to install cfssl on windows:
|
||||||
|
* [download](https://github.com/cloudflare/cfssl/releases/latest) `cfssl_windows_amd64.exe`, `cfssljson_windows_amd64.exe`, `cfssl-certinfo_windows_amd64.exe`
|
||||||
|
* rename them to `cfssl.exe`, `cfssljson.exe`, `cfssl-certinfo.exe`
|
||||||
|
* put them in PATH, for example inside `c:\windows\system32`
|
||||||
|
|
||||||
|
|
||||||
# recovering from crashes
|
# recovering from crashes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,10 @@ MOUNT_BASE = b"/run/media/egon/"
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
label = sys.argv[1].split(":usb-eject:")[1].split(":")[0]
|
msg = sys.argv[1]
|
||||||
|
if msg.startswith("upload-queue-empty;"):
|
||||||
|
return
|
||||||
|
label = msg.split(":usb-eject:")[1].split(":")[0]
|
||||||
mp = MOUNT_BASE + unquote(label)
|
mp = MOUNT_BASE + unquote(label)
|
||||||
# print("ejecting [%s]... " % (mp,), end="")
|
# print("ejecting [%s]... " % (mp,), end="")
|
||||||
mp = os.path.abspath(os.path.realpath(mp))
|
mp = os.path.abspath(os.path.realpath(mp))
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,9 @@ def do_stuff(inf):
|
||||||
log = inf["log"]
|
log = inf["log"]
|
||||||
|
|
||||||
url = inf["txt"]
|
url = inf["txt"]
|
||||||
|
if url.startswith("upload-queue-empty;"):
|
||||||
|
return
|
||||||
|
|
||||||
if "://" not in url:
|
if "://" not in url:
|
||||||
url = "https://" + url
|
url = "https://" + url
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@ while you're in the /inc folder (or any folder below there)
|
||||||
def main():
|
def main():
|
||||||
inf = json.loads(sys.argv[1])
|
inf = json.loads(sys.argv[1])
|
||||||
url = inf["txt"]
|
url = inf["txt"]
|
||||||
|
if url.startswith("upload-queue-empty;"):
|
||||||
|
return
|
||||||
|
|
||||||
if "://" not in url:
|
if "://" not in url:
|
||||||
url = "https://" + url
|
url = "https://" + url
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,18 +67,64 @@
|
||||||
# additional dependencies
|
# additional dependencies
|
||||||
extraPythonPackages ? (_p: [ ]),
|
extraPythonPackages ? (_p: [ ]),
|
||||||
|
|
||||||
|
# to build stable + unstable with the same file
|
||||||
|
stable ? true,
|
||||||
|
|
||||||
|
# for commit date, only used when stable = false
|
||||||
|
copypartyFlake ? null,
|
||||||
|
|
||||||
|
nix-gitignore,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
pinData = lib.importJSON ./pin.json;
|
pinData = lib.importJSON ./pin.json;
|
||||||
runtimeDeps = ([ util-linux ] ++ extraPackages ++ lib.optional withMediaProcessing ffmpeg);
|
runtimeDeps = ([ util-linux ] ++ extraPackages ++ lib.optional withMediaProcessing ffmpeg);
|
||||||
|
inherit (copypartyFlake) lastModifiedDate;
|
||||||
|
# ex: "1970" "01" "01"
|
||||||
|
dateStringsZeroPrefixed = {
|
||||||
|
year = builtins.substring 0 4 lastModifiedDate;
|
||||||
|
month = builtins.substring 4 2 lastModifiedDate;
|
||||||
|
day = builtins.substring 6 2 lastModifiedDate;
|
||||||
|
};
|
||||||
|
# ex: "1970" "1" "1"
|
||||||
|
dateStringsShort = builtins.mapAttrs (_: val: toString (lib.toIntBase10 val)) dateStringsZeroPrefixed;
|
||||||
|
unstableVersion =
|
||||||
|
if copypartyFlake == null then
|
||||||
|
"${pinData.version}-unstable"
|
||||||
|
else
|
||||||
|
with dateStringsZeroPrefixed; "${pinData.version}-unstable-${year}-${month}-${day}"
|
||||||
|
;
|
||||||
|
version = if stable then pinData.version else unstableVersion;
|
||||||
|
stableSrc = fetchurl {
|
||||||
|
inherit (pinData) url hash;
|
||||||
|
};
|
||||||
|
root = ../../../..;
|
||||||
|
unstableSrc = nix-gitignore.gitignoreSource [] root;
|
||||||
|
src = if stable then stableSrc else unstableSrc;
|
||||||
|
rev = copypartyFlake.shortRev or copypartyFlake.dirtyShortRev or "unknown";
|
||||||
|
unstableCodename = "unstable" + (lib.optionalString (copypartyFlake != null) "-${rev}");
|
||||||
in
|
in
|
||||||
buildPythonApplication {
|
buildPythonApplication {
|
||||||
pname = "copyparty";
|
pname = "copyparty";
|
||||||
inherit (pinData) version;
|
inherit version src;
|
||||||
src = fetchurl {
|
postPatch = lib.optionalString (!stable) ''
|
||||||
inherit (pinData) url hash;
|
old_src="$(mktemp -d)"
|
||||||
};
|
tar -C "$old_src" -xf ${stableSrc}
|
||||||
|
declare -a folders
|
||||||
|
folders=("$old_src"/*)
|
||||||
|
count_folders="''${#folders[@]}"
|
||||||
|
if [[ $count_folders != 1 ]]; then
|
||||||
|
declare -p folders
|
||||||
|
echo "Expected 1 folder, found $count_folders" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
old_src_folder="''${folders[0]}"
|
||||||
|
cp -r "$old_src_folder"/copyparty/web/deps copyparty/web/deps
|
||||||
|
sed -i 's/^CODENAME =.*$/CODENAME = "${unstableCodename}"/' copyparty/__version__.py
|
||||||
|
${lib.optionalString (copypartyFlake != null) (with dateStringsShort; ''
|
||||||
|
sed -i 's/^BUILD_DT =.*$/BUILD_DT = (${year}, ${month}, ${day})/' copyparty/__version__.py
|
||||||
|
'')}
|
||||||
|
'';
|
||||||
dependencies =
|
dependencies =
|
||||||
[
|
[
|
||||||
jinja2
|
jinja2
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,28 @@
|
||||||
final: prev: {
|
final: prev:
|
||||||
copyparty = final.python3.pkgs.callPackage ./copyparty {
|
let
|
||||||
ffmpeg = final.ffmpeg-full;
|
fullAttrs = {
|
||||||
|
withHashedPasswords = true;
|
||||||
|
withCertgen = true;
|
||||||
|
withThumbnails = true;
|
||||||
|
withFastThumbnails = true;
|
||||||
|
withMediaProcessing = true;
|
||||||
|
withBasicAudioMetadata = true;
|
||||||
|
withZeroMQ = true;
|
||||||
|
withFTP = true;
|
||||||
|
withFTPS = true;
|
||||||
|
withTFTP = true;
|
||||||
|
withSMB = true;
|
||||||
|
withMagic = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
call = attrs: final.python3.pkgs.callPackage ./copyparty ({ ffmpeg = final.ffmpeg-full; } // attrs);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
copyparty = call { stable = true; };
|
||||||
|
copyparty-unstable = call { stable = false; };
|
||||||
|
copyparty-full = call (fullAttrs // { stable = true; });
|
||||||
|
copyparty-unstable-full = call (fullAttrs // { stable = false; });
|
||||||
|
|
||||||
python3 = prev.python3.override {
|
python3 = prev.python3.override {
|
||||||
packageOverrides = pyFinal: pyPrev: {
|
packageOverrides = pyFinal: pyPrev: {
|
||||||
partftpy = pyFinal.callPackage ./partftpy { };
|
partftpy = pyFinal.callPackage ./partftpy { };
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import calendar
|
||||||
import errno
|
import errno
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from .__init__ import ANYWIN
|
from .__init__ import ANYWIN
|
||||||
|
|
@ -19,6 +20,19 @@ else:
|
||||||
VF = {"mv_re_t": 0, "rm_re_t": 0}
|
VF = {"mv_re_t": 0, "rm_re_t": 0}
|
||||||
|
|
||||||
|
|
||||||
|
def _sp_err(exe, what, rc, so, se, sin):
|
||||||
|
try:
|
||||||
|
zs = shutil.which(exe)
|
||||||
|
except:
|
||||||
|
zs = "<?>"
|
||||||
|
try:
|
||||||
|
zi = os.path.getsize(zs)
|
||||||
|
except:
|
||||||
|
zi = 0
|
||||||
|
t = "failed to %s; error %s using %s (%s):\n STDOUT: %s\n STDERR: %s\n STDIN: %s\n"
|
||||||
|
raise Exception(t % (what, rc, zs, zi, so, se, sin.decode("utf-8")))
|
||||||
|
|
||||||
|
|
||||||
def ensure_cert(log: "RootLogger", args) -> None:
|
def ensure_cert(log: "RootLogger", args) -> None:
|
||||||
"""
|
"""
|
||||||
the default cert (and the entire TLS support) is only here to enable the
|
the default cert (and the entire TLS support) is only here to enable the
|
||||||
|
|
@ -107,13 +121,13 @@ def _gen_ca(log: "RootLogger", args):
|
||||||
cmd = "cfssl gencert -initca -"
|
cmd = "cfssl gencert -initca -"
|
||||||
rc, so, se = runcmd(cmd.split(), 30, sin=sin)
|
rc, so, se = runcmd(cmd.split(), 30, sin=sin)
|
||||||
if rc:
|
if rc:
|
||||||
raise Exception("failed to create ca-cert: {}, {}".format(rc, se), 3)
|
_sp_err("cfssl", "create ca-cert", rc, so, se, sin)
|
||||||
|
|
||||||
cmd = "cfssljson -bare ca"
|
cmd = "cfssljson -bare ca"
|
||||||
sin = so.encode("utf-8")
|
sin = so.encode("utf-8")
|
||||||
rc, so, se = runcmd(cmd.split(), 10, sin=sin, cwd=args.crt_dir)
|
rc, so, se = runcmd(cmd.split(), 10, sin=sin, cwd=args.crt_dir)
|
||||||
if rc:
|
if rc:
|
||||||
raise Exception("failed to translate ca-cert: {}, {}".format(rc, se), 3)
|
_sp_err("cfssljson", "translate ca-cert", rc, so, se, sin)
|
||||||
|
|
||||||
bname = os.path.join(args.crt_dir, "ca")
|
bname = os.path.join(args.crt_dir, "ca")
|
||||||
try:
|
try:
|
||||||
|
|
@ -201,13 +215,13 @@ def _gen_srv(log: "RootLogger", args, netdevs: dict[str, Netdev]):
|
||||||
acmd = cmd.split() + ["-hostname=" + ",".join(names), "-"]
|
acmd = cmd.split() + ["-hostname=" + ",".join(names), "-"]
|
||||||
rc, so, se = runcmd(acmd, 30, sin=sin, cwd=args.crt_dir)
|
rc, so, se = runcmd(acmd, 30, sin=sin, cwd=args.crt_dir)
|
||||||
if rc:
|
if rc:
|
||||||
raise Exception("failed to create cert: {}, {}".format(rc, se))
|
_sp_err("cfssl", "create cert", rc, so, se, sin)
|
||||||
|
|
||||||
cmd = "cfssljson -bare srv"
|
cmd = "cfssljson -bare srv"
|
||||||
sin = so.encode("utf-8")
|
sin = so.encode("utf-8")
|
||||||
rc, so, se = runcmd(cmd.split(), 10, sin=sin, cwd=args.crt_dir)
|
rc, so, se = runcmd(cmd.split(), 10, sin=sin, cwd=args.crt_dir)
|
||||||
if rc:
|
if rc:
|
||||||
raise Exception("failed to translate cert: {}, {}".format(rc, se))
|
_sp_err("cfssljson", "translate cert", rc, so, se, sin)
|
||||||
|
|
||||||
bname = os.path.join(args.crt_dir, "srv")
|
bname = os.path.join(args.crt_dir, "srv")
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -2449,7 +2449,7 @@ function mpause(e) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
dist *= -1;
|
dist *= -1;
|
||||||
mp.setvol(mp.vol + dist / 500);
|
mp.setvol(Math.round((mp.vol + dist / 500) * 100) / 100 );
|
||||||
vbar.draw();
|
vbar.draw();
|
||||||
ev(e);
|
ev(e);
|
||||||
};
|
};
|
||||||
|
|
@ -3019,9 +3019,6 @@ function play(tid, is_ev, seek) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tn >= mp.order.length) {
|
if (tn >= mp.order.length) {
|
||||||
if (mpl.pb_mode == 'stop')
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mpl.pb_mode == 'loop' || ebi('unsearch')) {
|
if (mpl.pb_mode == 'loop' || ebi('unsearch')) {
|
||||||
tn = 0;
|
tn = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -3029,6 +3026,7 @@ function play(tid, is_ev, seek) {
|
||||||
treectl.ls_cb = next_song;
|
treectl.ls_cb = next_song;
|
||||||
return tree_neigh(1);
|
return tree_neigh(1);
|
||||||
}
|
}
|
||||||
|
else return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tn < 0) {
|
if (tn < 0) {
|
||||||
|
|
@ -3039,6 +3037,7 @@ function play(tid, is_ev, seek) {
|
||||||
treectl.ls_cb = last_song;
|
treectl.ls_cb = last_song;
|
||||||
return tree_neigh(-1);
|
return tree_neigh(-1);
|
||||||
}
|
}
|
||||||
|
else return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tid = mp.order[tn];
|
tid = mp.order[tn];
|
||||||
|
|
|
||||||
|
|
@ -2271,11 +2271,17 @@ function up2k_init(subtle) {
|
||||||
busy = {},
|
busy = {},
|
||||||
nbusy = 0,
|
nbusy = 0,
|
||||||
init = 0,
|
init = 0,
|
||||||
|
ninit = 0,
|
||||||
hashtab = {},
|
hashtab = {},
|
||||||
mem = (MOBILE ? 128 : 256) * 1024 * 1024;
|
mem = (MOBILE ? 128 : 256) * 1024 * 1024;
|
||||||
|
|
||||||
if (!hws_ok)
|
if (!hws_ok)
|
||||||
init = setTimeout(function() {
|
init = setInterval(function() {
|
||||||
|
if (ninit < hws_ok) {
|
||||||
|
ninit = hws_ok;
|
||||||
|
return toast.inf(10, 'initializing webworkers ({0}/{1})'.format(hws_ok, hws.length), "iwwt");
|
||||||
|
}
|
||||||
|
clearInterval(init);
|
||||||
hws_ng = true;
|
hws_ng = true;
|
||||||
toast.warn(30, 'webworkers failed to start\n\nwill be a bit slower due to\nhashing on main-thread');
|
toast.warn(30, 'webworkers failed to start\n\nwill be a bit slower due to\nhashing on main-thread');
|
||||||
apop(st.busy.hash, t);
|
apop(st.busy.hash, t);
|
||||||
|
|
@ -2325,12 +2331,17 @@ function up2k_init(subtle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onmsg(d) {
|
function onmsg(d) {
|
||||||
|
if (hws_ng)
|
||||||
|
return;
|
||||||
|
|
||||||
d = d.data;
|
d = d.data;
|
||||||
var k = d[0];
|
var k = d[0];
|
||||||
|
|
||||||
if (k == "pong")
|
if (k == "pong")
|
||||||
if (++hws_ok == hws.length) {
|
if (++hws_ok == hws.length) {
|
||||||
clearTimeout(init);
|
clearInterval(init);
|
||||||
|
if (toast.tag == 'iwwt')
|
||||||
|
toast.hide();
|
||||||
go_next();
|
go_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
[/] # create a volume at "/" (the webroot), which will
|
[/] # create a volume at "/" (the webroot), which will
|
||||||
/w # share /w (the docker data volume)
|
/w # share /w (the docker data volume)
|
||||||
accs:
|
accs:
|
||||||
rw: * # everyone gets read-access, but
|
r: * # everyone gets read-access, but
|
||||||
rwmda: @su # the group "su" gets read-write-move-delete-admin
|
rwmda: @su # the group "su" gets read-write-move-delete-admin
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
25
flake.nix
25
flake.nix
|
|
@ -12,7 +12,8 @@
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
nixosModules.default = ./contrib/nixos/modules/copyparty.nix;
|
nixosModules.default = ./contrib/nixos/modules/copyparty.nix;
|
||||||
overlays.default = import ./contrib/package/nix/overlay.nix;
|
overlays.default = final: prev:
|
||||||
|
(import ./contrib/package/nix/overlay.nix final prev) // { copypartyFlake = self; };
|
||||||
}
|
}
|
||||||
// flake-utils.lib.eachDefaultSystem (
|
// flake-utils.lib.eachDefaultSystem (
|
||||||
system:
|
system:
|
||||||
|
|
@ -22,26 +23,26 @@
|
||||||
config = {
|
config = {
|
||||||
allowAliases = false;
|
allowAliases = false;
|
||||||
};
|
};
|
||||||
overlays = [ self.overlays.default ];
|
overlays = [
|
||||||
|
self.overlays.default
|
||||||
|
];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# check that copyparty builds with all optionals turned on
|
# check that copyparty builds with all optionals turned on
|
||||||
checks.copyparty-full = self.packages.${system}.copyparty.override {
|
checks = {
|
||||||
withHashedPasswords = true;
|
inherit (pkgs)
|
||||||
withCertgen = true;
|
copyparty-full
|
||||||
withThumbnails = true;
|
copyparty-unstable-full
|
||||||
withFastThumbnails = true;
|
;
|
||||||
withMediaProcessing = true;
|
|
||||||
withBasicAudioMetadata = true;
|
|
||||||
withZeroMQ = true;
|
|
||||||
withFTPS = true;
|
|
||||||
withSMB = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = {
|
packages = {
|
||||||
inherit (pkgs)
|
inherit (pkgs)
|
||||||
copyparty
|
copyparty
|
||||||
|
copyparty-full
|
||||||
|
copyparty-unstable
|
||||||
|
copyparty-unstable-full
|
||||||
;
|
;
|
||||||
default = self.packages.${system}.copyparty;
|
default = self.packages.${system}.copyparty;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
command -v gfind >/dev/null &&
|
||||||
|
command -v gsed >/dev/null &&
|
||||||
|
command -v gsort >/dev/null && {
|
||||||
|
sed() { gsed "$@"; }
|
||||||
|
}
|
||||||
|
|
||||||
[ -e make-sfx.sh ] || cd scripts
|
[ -e make-sfx.sh ] || cd scripts
|
||||||
[ -e make-sfx.sh ] && [ -e deps-docker ] || {
|
[ -e make-sfx.sh ] && [ -e deps-docker ] || {
|
||||||
echo cd into the scripts folder first
|
echo cd into the scripts folder first
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,12 @@ def cnv(src):
|
||||||
hostname = str(socket.gethostname()).split(".")[0]
|
hostname = str(socket.gethostname()).split(".")[0]
|
||||||
|
|
||||||
yield '<!DOCTYPE html>'
|
yield '<!DOCTYPE html>'
|
||||||
yield '<html style="background:#222;color:#fff"><body>'
|
yield '<html><body><style>'
|
||||||
|
yield 'html{background:#222;color:#fff;line-height:1.25em}'
|
||||||
|
yield 'h3{margin:0;padding:0}'
|
||||||
|
yield 'a{color:#fc5;text-decoration:none;scroll-margin-top:3em}'
|
||||||
|
yield 'a:active,a:target{background:#fc5;color:#000;box-shadow:0 0 0 .12em #fc5}'
|
||||||
|
yield '</style>'
|
||||||
skip_sfx = False
|
skip_sfx = False
|
||||||
in_sfx = 0
|
in_sfx = 0
|
||||||
in_salt = 0
|
in_salt = 0
|
||||||
|
|
@ -104,6 +109,15 @@ def cnv(src):
|
||||||
ln = re.sub(r">[0-9]{1,2}\.[0-9]<", ">dynamic<", ln)
|
ln = re.sub(r">[0-9]{1,2}\.[0-9]<", ">dynamic<", ln)
|
||||||
if t != ln:
|
if t != ln:
|
||||||
in_th_ram_max = 0
|
in_th_ram_max = 0
|
||||||
|
m = re.search(r"^# (.* help page)(.*)", ln)
|
||||||
|
if m:
|
||||||
|
zs1, zs2 = m.groups()
|
||||||
|
zs3 = zs1.replace(" ", "-")
|
||||||
|
ln = '<h3># <a id="%s" href="#%s">%s</a>%s</h3></a>' % (zs3, zs3, zs1, zs2)
|
||||||
|
m = re.search(r"^ (-{1,2})([^ ,]+)(.*)", ln)
|
||||||
|
if m:
|
||||||
|
zs1, zs2, zs3 = m.groups()
|
||||||
|
ln = ' <a href="#g-%s" id="g-%s">%s%s</a>%s' % (zs2, zs2, zs1, zs2, zs3)
|
||||||
|
|
||||||
ln = ln.replace(">/home/ed/", ">~/")
|
ln = ln.replace(">/home/ed/", ">~/")
|
||||||
if ln.startswith("0" * 20):
|
if ln.startswith("0" * 20):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
command -v gfind >/dev/null &&
|
||||||
|
command -v gsed >/dev/null &&
|
||||||
|
command -v gsort >/dev/null && {
|
||||||
|
head() { ghead "$@"; }
|
||||||
|
}
|
||||||
|
|
||||||
( ( HLPTXT=CAT && cat || xsel -ob ) | sed -r '
|
( ( HLPTXT=CAT && cat || xsel -ob ) | sed -r '
|
||||||
s`/home/ed/`~/`;
|
s`/home/ed/`~/`;
|
||||||
s/uuid:[0-9a-f-]{36}/autogenerated/;
|
s/uuid:[0-9a-f-]{36}/autogenerated/;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue