๐Ÿ“ฆโž”๐Ÿฆ‹ Store and retrieve files on the ATmosphere

Compare changes

Choose any two refs to compare.

+568 -546
+16 -1
.tangled/workflows/build.yaml
··· 14 14 dependencies: 15 15 nixpkgs: 16 16 - bash 17 + - coreutils 18 + - curl 19 + - exiftool 20 + - file 21 + - git 22 + - gnugrep 23 + - gnused 24 + - hostname 25 + - jq 26 + - mediainfo 17 27 - shellcheck 18 28 19 29 environment: 30 + ATFILE_DEBUG: "0" 20 31 ATFILE_DEVEL_ENABLE_PUBLISH: "0" 21 32 22 33 steps: 23 - - name: "Build" 34 + - name: "ATFile: List files for @zio.sh" 35 + command: "./atfile.sh ls zio.sh" 36 + - name: "ATFile: Print debug output" 37 + command: "./atfile.sh something-broke" 38 + - name: "ATFile: Build" 24 39 command: "./atfile.sh build"
+10 -6
README.md
··· 41 41 * [MediaInfo (`mediainfo`)](https://mediaarea.net/en/MediaInfo) _(optional: set `ATFILE_DISABLE_NI_MEDIAINFO=1` to ignore)_ 42 42 * `md5sum` _(optional: set `ATFILE_DISABLE_NI_MD5SUM=1` to ignore)_ 43 43 * Both GNU and BusyBox versions supported 44 + * `sed` 45 + * Only GNU version supported 44 46 * [`websocat`](https://github.com/vi/websocat) _(optional: needed for `stream`)_ 45 47 * **ATProto account** 46 48 * Limit the amount of files you upload, and avoid copyrighted files, if using a managed PDS<br /><em>(e.g. [Blacksky](https://pds.blacksky.app), [Bluesky](https://bsky.social), [Spark](https://pds.sprk.so), [Tangled](https://tngl.sh), or any other independent PDS you don't own)</eM> ··· 67 69 * __Linux/*BSD/Solaris/SerenityOS__ 68 70 * Install: `$HOME/.local/bin/atfile` 69 71 * As `sudo`/`root`: `/usr/local/bin/atfile` 72 + * On **Termux:** `/usr/bin/atfile` 70 73 * Config: `$HOME/.config/atfile.env`, **or** `$XDG_CONFIG_HOME/atfile.env` (if set) 71 74 * **macOS** 72 75 * Install: `$HOME/.local/bin/atfile` ··· 102 105 103 106 Various environment variables can be exported to control various aspects of the development version. These are as follows: 104 107 108 + * `ATFILE_DEVEL_DIST_USERNAME` <em>&lt;string&gt;</em><br />_(Todo)_. During runtime, this is set to `$did` in `atfile.sh` (see **๐Ÿ—๏ธ Building โž” Meta**). Ideally, you should not set this variable as updates in the built version will not be fetched from the correct place 109 + * `ATFILE_DEVEL_DIST_PASSWORD` <em>&lt;string&gt;</em><br />_(Todo)_ 105 110 * `ATFILE_DEVEL_ENABLE_PIPING` <em>&lt;int&gt; (default: `0`)</em><br />Allow piping (useful to test installation) _(e.g. `cat ./atfile.sh | bash`)_ 106 - * `ATFILE_DEVEL_ENABLE_PUBLISH` <em>&lt;int&gt; (default: `0`)</em><br />Publish build to ATProto repository (to allow for updating) as the last step when running `release`. Several requirements must be fulfilled to succeed: 107 - * `ATFILE_DEVEL_DIST_USERNAME` must be set<br />By default, this is set to `$did` in `atfile.sh` (see **๐Ÿ—๏ธ Building โž” Meta**). Ideally, you should not set this variable as updates in the built version will not be fetched from the correct place 111 + * `ATFILE_DEVEL_ENABLE_PUBLISH` <em>&lt;int&gt; (default: `0`)</em><br />Publish build to ATProto repository (to allow for updating) as the last step when running `build`. Several requirements must be fulfilled: 112 + * `ATFILE_DEVEL_DIST_USERNAME` must be set 108 113 * `ATFILE_DEVEL_DIST_PASSWORD` must be set 109 114 * No tests should return an **Error** (**Warning** is acceptable) 110 115 * Git commit must be <a href="https://git-scm.com/docs/git-tag">tagged</a> ··· 119 124 120 125 ### Meta 121 126 122 - Various meta variables can be set to be available in the final compiled build (usually found in `help`). These are found in `atfile.sh` under `# Meta`. These variables are as follows: 127 + Various meta variables can be set to be available in the final compiled build (usually found in `help`). These are found in `atfile.sh` under `# Meta`. These are as follows: 123 128 124 129 * `author` <em>&lt;string&gt;</em><br />Copyright author 125 130 * `did` <em>&lt;did&gt;</em><br />DID of copyright author. Also used as the source for published builds, unless `ATFILE_DEVEL_DIST_USERNAME` is set (see **๐Ÿ—๏ธ Building โž” Environment variables**) ··· 137 142 138 143 * **Paul Frazee** &mdash; [๐Ÿฆ‹ @pfrazee.com](https://bsky.app/profile/did:plc:ragtjsm2j2vknwkz3zp4oxrd)<br /><a href="https://bsky.app/profile/did:plc:ragtjsm2j2vknwkz3zp4oxrd/post/3l63zzvthqj2o">His kind words</a> 139 144 * **Laurens Hof** &mdash; [๐Ÿฆ‹ @laurenshof.online](https://bsky.app/profile/did:plc:mdjhvva6vlrswsj26cftjttd)<br />Featuring ATFile on [The Fediverse Report](https://fediversereport.com): _["Last Week in the ATmosphere โ€“ Oct 2024 week 4"](https://fediversereport.com/last-week-in-the-atmosphere-oct-2024-week-4/)_ 140 - * **Samir** &mdash; [๐Ÿ™ @bdotsamir](https://github.com/bdotsamir)<br />Testing, and diagnosing problems with, support for macOS (`macos`) 141 - * **Astra** &mdash; [๐Ÿฆ‹ @astra.blue](https://bsky.app/profile/did:plc:ejy6lkhb72rxvkk57tnrmpjl)<br />[Various PRs](https://github.com/ziodotsh/atfile/pulls?q=is%3Apr+author%3Aastravexton); testing, and diagnosing problems with, support for MinGW (`linux-mingw`) and Termux (`linux-termux`) 145 + * All contributors on [Tangled](https://tangled.org/@zio.sh/atfile/pulls) and [GitHub](https://github.com/ziodotsh/atfile/pulls) 142 146 * _(Forgot about you? [You know what to do](https://tangled.sh/@zio.sh/atfile/pulls/new))_ 143 147 144 148 --- ··· 149 153 * **ยฒ** musl-powered distros do not use GNU/glibc packages, and have problems currently 150 154 * Known musl distros: Alpine, Chimera, Dragora, Gentoo (musl), Morpheus, OpenWrt, postmarketOS, Sabotage, Void 151 155 * Bypassing OS detection (see ยน) will cause unintended behavior 152 - * **ยณ** As long as you have Bash installed, running from another shell will not be problematic ([`#!/usr/bin/env bash`](https://tangled.sh/@zio.sh/atfile/blob/main/atfile-install.sh#L1) forces Bash) 156 + * **ยณ** As long as you have Bash installed, running from another shell will not be problematic ([`#!/usr/bin/env bash`](https://tangled.sh/@zio.sh/atfile/blob/main/atfile.sh#L1) forces Bash)
+1 -1
atfile.sh
··· 36 36 author="zio" 37 37 did="did:web:zio.sh" 38 38 repo="https://tangled.sh/@zio.sh/atfile" 39 - version="0.12.2" 39 + version="0.12.8" 40 40 year="$(date +%Y)" 41 41 42 42 # Entry
+1 -1
src/commands/auth.sh
··· 31 31 # NOTE: Speeds things up a little if the command doesn't need actor resolving 32 32 if [[ -z $_command ]] ||\ 33 33 [[ $_command == "ai" ]] ||\ 34 + [[ $_command == "build" ]] ||\ 34 35 [[ $_command == "handle" ]] ||\ 35 36 [[ $_command == "help" ]] ||\ 36 37 [[ $_command == "now" ]] ||\ 37 - [[ $_command == "release" ]] ||\ 38 38 [[ $_command == "resolve" ]] ||\ 39 39 [[ $_command == "scrape" ]] ||\ 40 40 [[ $_command == "something-broke" ]] ||\
+214
src/commands/build.sh
··· 1 + #!/usr/bin/env bash 2 + # atfile-devel=ignore-build 3 + 4 + function atfile.build() { 5 + # shellcheck disable=SC2154 6 + [[ $_os != "linux" ]] && atfile.die "Only available on Linux (GNU)\nโ†ณ Detected OS: $_os" 7 + 8 + function atfile.build.get_devel_value() { 9 + local file="$1" 10 + local value="$2" 11 + local found_line 12 + 13 + found_line="$(grep '^# atfile-devel=' "$file" | head -n1)" 14 + if [[ -n "$found_line" ]]; then 15 + local devel_values="${found_line#*=}" 16 + IFS=',' read -ra arr <<< "$devel_values" 17 + for v in "${arr[@]}"; do 18 + if [[ "$v" == "$value" ]]; then 19 + echo 1 20 + fi 21 + done 22 + fi 23 + } 24 + 25 + function atfile.build.replace_template_var() { 26 + string="$1" 27 + key="$2" 28 + value="$3" 29 + 30 + sed -s "s|{:$key:}|$value|g" <<< "$string" 31 + } 32 + 33 + function atfile.build.pad_emoji() { 34 + emoji="$1" 35 + padding="$2" 36 + 37 + # shellcheck disable=SC2154 38 + if [[ $_ci == "tangled" ]]; then 39 + atfile.say.inline "$emoji" 40 + else 41 + atfile.say.inline "$emoji$padding" 42 + fi 43 + } 44 + 45 + atfile.util.check_prog "git" 46 + atfile.util.check_prog "grep" 47 + atfile.util.check_prog "hostname" 48 + atfile.util.check_prog "md5sum" 49 + atfile.util.check_prog "sed" 50 + atfile.util.check_prog "shellcheck" 51 + 52 + id="$(atfile.util.get_random 13)" 53 + commit_author="$(git config user.name) <$(git config user.email)>" 54 + commit_hash="$(git rev-parse HEAD)" 55 + commit_date="$(git show --no-patch --format=%ci "$commit_hash")" 56 + # shellcheck disable=SC2154 57 + dist_file="$(echo "$_prog" | cut -d "." -f 1)-${_version}.sh" 58 + # shellcheck disable=SC2154 59 + dist_dir="$_prog_dir/bin" 60 + dist_path="$dist_dir/$dist_file" 61 + dist_path_relative="$(realpath --relative-to="$(pwd)" "$dist_path" 2>/dev/null)" 62 + parsed_version="$(atfile.util.parse_version "$_version")" 63 + version_record_id="atfile-$parsed_version" 64 + 65 + test_error_count=0 66 + test_info_count=0 67 + test_style_count=0 68 + test_warning_count=0 69 + test_ignore_count=0 70 + 71 + if [[ -z "$dist_path_relative" ]]; then 72 + dist_path_relative="$dist_path" 73 + else 74 + dist_path_relative="./$dist_path_relative" 75 + fi 76 + 77 + atfile.say "$(atfile.build.pad_emoji "โš’๏ธ" " ") Building..." 78 + 79 + echo "โ†ณ Creating '$dist_file'..." 80 + mkdir -p "$dist_dir" 81 + echo "#!/usr/bin/env bash" > "$dist_path" 82 + 83 + echo "โ†ณ Generating header..." 84 + echo -e "\n# ATFile <${ATFILE_FORCE_META_REPO}> 85 + # --- 86 + # Version: $_version 87 + # Commit: $commit_hash 88 + # Author: $commit_author 89 + # Build: $id ($(hostname):$(atfile.util.get_os)) 90 + # --- 91 + # Psst! You can \`source atfile\` in your own Bash scripts! 92 + " >> "$dist_path" 93 + 94 + for s in "${ATFILE_DEVEL_INCLUDES[@]}" 95 + do 96 + if [[ -f "$s" ]]; then 97 + if [[ $(atfile.build.get_devel_value "$s" "ignore-build" == 1 ) ]]; then 98 + echo "โ†ณ Ignoring: $s" 99 + else 100 + echo "โ†ณ Compiling: $s" 101 + 102 + while IFS="" read -r line 103 + do 104 + include_line=1 105 + 106 + if [[ $line == "#"* ]] ||\ 107 + [[ $line == *" #"* ]] ||\ 108 + [[ $line == " " ]] ||\ 109 + [[ $line == "" ]]; then 110 + include_line=0 111 + fi 112 + 113 + if [[ $line == *"# shellcheck disable"* ]]; then 114 + if [[ $line == *"=SC2154"* ]]; then 115 + include_line=0 116 + else 117 + include_line=1 118 + (( test_ignore_count++ )) 119 + fi 120 + fi 121 + 122 + if [[ $include_line == 1 ]]; then 123 + if [[ $line == *"{:"* && $line == *":}"* ]]; then 124 + # NOTE: Not using atfile.util.get_envvar() here, as confusion can arise from config file 125 + line="$(atfile.build.replace_template_var "$line" "meta_author" "$ATFILE_FORCE_META_AUTHOR")" 126 + line="$(atfile.build.replace_template_var "$line" "meta_did" "$ATFILE_FORCE_META_DID")" 127 + line="$(atfile.build.replace_template_var "$line" "meta_repo" "$ATFILE_FORCE_META_REPO")" 128 + line="$(atfile.build.replace_template_var "$line" "meta_year" "$ATFILE_FORCE_META_YEAR")" 129 + line="$(atfile.build.replace_template_var "$line" "version" "$ATFILE_FORCE_VERSION")" 130 + fi 131 + 132 + echo "$line" >> "$dist_path" 133 + fi 134 + done < "$s" 135 + fi 136 + fi 137 + done 138 + 139 + echo -e "\n# \"Four million lines of BASIC\"\n# - Kif Kroker (3003)" >> "$dist_path" 140 + 141 + checksum="$(atfile.util.get_md5 "$dist_path" | cut -d "|" -f 1)" 142 + 143 + echo "๐Ÿงช Testing..." 144 + shellcheck_output="$(shellcheck --format=json "$dist_path" 2>&1)" 145 + 146 + while read -r item; do 147 + code="$(echo "$item" | jq -r '.code')" 148 + col="$(echo "$item" | jq -r '.column')" 149 + line="$(echo "$item" | jq -r '.line')" 150 + level="$(echo "$item" | jq -r '.level')" 151 + message="$(echo "$item" | jq -r '.message')" 152 + 153 + case "$level" in 154 + "error") level="$(atfile.build.pad_emoji "๐Ÿ›‘" "") Error"; (( test_error_count++ )) ;; 155 + "info") level="$(atfile.build.pad_emoji "โ„น๏ธ" " ") Info"; (( test_info_count++ )) ;; 156 + "style") level="$(atfile.build.pad_emoji "๐ŸŽจ" "") Style"; (( test_style_count++ )) ;; 157 + "warning") level="$(atfile.build.pad_emoji "โš ๏ธ" " ") Warning"; (( test_warning_count++ )) ;; 158 + esac 159 + 160 + echo "โ†ณ $level ($line:$col): [SC$code] $message" 161 + done <<< "$(echo "$shellcheck_output" | jq -c '.[]')" 162 + 163 + test_total_count=$(( test_error_count + test_info_count + test_style_count + test_warning_count )) 164 + 165 + end_message_suffix_string="โ†ณ Issues: $(atfile.util.fmt_int "$test_total_count") 166 + โ†ณ Error: $(atfile.util.fmt_int "$test_error_count") 167 + โ†ณ Warning: $(atfile.util.fmt_int "$test_warning_count") 168 + โ†ณ Info: $(atfile.util.fmt_int "$test_info_count") 169 + โ†ณ Style: $(atfile.util.fmt_int "$test_style_count") 170 + โ†ณ Ignored: $(atfile.util.fmt_int "$test_ignore_count") 171 + โ†ณ ID: $id" 172 + 173 + atfile.say "---" 174 + 175 + if [[ $test_error_count -gt 0 ]]; then 176 + atfile.say "$(atfile.build.pad_emoji "โ›”" "") Failed: $_version 177 + $end_message_suffix_string" "" 31 31 1 178 + rm -f "$dist_path" 179 + exit 255 180 + else 181 + echo -e "$(atfile.build.pad_emoji "โœ…" "") Built: $_version 182 + โ†ณ Path: $dist_path_relative 183 + โ†ณ Check: $checksum 184 + โ†ณ Size: $(atfile.util.get_file_size_pretty "$(stat -c %s "$dist_path")") 185 + โ†ณ Lines: $(atfile.util.fmt_int "$(wc -l < "$dist_path")") 186 + $end_message_suffix_string" 187 + fi 188 + 189 + chmod +x "$dist_path" 190 + 191 + # shellcheck disable=SC2154 192 + if [[ $_devel_enable_publish == 1 ]]; then 193 + atfile.say "---\n$(atfile.build.pad_emoji "โœจ" "") Updating..." 194 + atfile.auth "$_devel_dist_username" "$_devel_dist_password" 195 + [[ $_version == *"+"* ]] && atfile.die "Cannot publish a Git version ($_version)" 196 + 197 + atfile.say "โ†ณ Uploading '$dist_path'..." 198 + atfile.invoke.upload "$dist_path" "" "$version_record_id" 199 + # shellcheck disable=SC2181 200 + [[ $? != 0 ]] && atfile.die "Unable to upload '$dist_path'" 201 + 202 + latest_release_record="{ 203 + \"version\": \"$_version\", 204 + \"releasedAt\": \"$(atfile.util.get_date "$commit_date")\", 205 + \"commit\": \"$commit_hash\", 206 + \"id\": \"$id\", 207 + \"checksum\": \"$checksum\" 208 + }" 209 + 210 + atfile.say "---\n$(atfile.build.pad_emoji "โฌ†๏ธ" " ") Bumping..." 211 + # shellcheck disable=SC2154 212 + atfile.record update "at://$_devel_dist_username/self.atfile.latest/self" "$latest_release_record" 213 + fi 214 + }
+109
src/commands/handle.sh
··· 1 + #!/usr/bin/env bash 2 + 3 + function atfile.handle() { 4 + uri="$1" 5 + handler="$2" 6 + 7 + function atfile.handle.is_temp_file_needed() { 8 + handler="${1//.desktop/}" 9 + type="$2" 10 + 11 + handlers_needing_tmp_file=( 12 + "app.drey.EarTag" 13 + "com.github.neithern.g4music" 14 + ) 15 + 16 + if [[ ${handlers_needing_tmp_file[*]} =~ $handler ]]; then 17 + echo 1 18 + elif [[ $type == "text/"* ]]; then 19 + echo 1 20 + else 21 + echo 0 22 + fi 23 + } 24 + 25 + # shellcheck disable=SC2154 26 + [[ $_output_json == 1 ]] && atfile.die "Command not available as JSON" 27 + 28 + actor="$(echo "$uri" | cut -d "/" -f 3)" 29 + key="$(echo "$uri" | cut -d "/" -f 4)" 30 + 31 + # shellcheck disable=SC2154 32 + atfile.util.create_dir "$_path_blobs_tmp" 33 + 34 + if [[ -n "$actor" && -n "$key" ]]; then 35 + atfile.util.override_actor "$actor" 36 + 37 + # shellcheck disable=SC2154 38 + atfile.say.debug "Getting record...\nโ†ณ NSID: $_nsid_upload\nโ†ณ Repo: $_username\nโ†ณ Key: $key" 39 + record="$(com.atproto.repo.getRecord "$_username" "$_nsid_upload" "$key")" 40 + error="$(atfile.util.get_xrpc_error $? "$record")" 41 + [[ -n "$error" ]] && atfile.die.gui.xrpc_error "Unable to get '$key'" "$error" 42 + 43 + blob_cid="$(echo "$record" | jq -r ".value.blob.ref.\"\$link\"")" 44 + blob_uri="$(atfile.util.build_blob_uri "$_username" "$blob_cid")" 45 + file_type="$(echo "$record" | jq -r '.value.file.mimeType')" 46 + 47 + # shellcheck disable=SC2154 48 + if [[ $_os == "linux"* ]] && \ 49 + [ -x "$(command -v xdg-mime)" ] && \ 50 + [ -x "$(command -v xdg-open)" ] && \ 51 + [ -x "$(command -v gtk-launch)" ]; then 52 + 53 + # HACK: Open with browser if $file_type isn't set 54 + [[ -z $file_type ]] && file_type="text/html" 55 + 56 + if [[ -z $handler ]]; then 57 + atfile.say.debug "Querying for handler '$file_type'..." 58 + handler="$(xdg-mime query default "$file_type")" 59 + else 60 + handler="$handler.desktop" 61 + atfile.say.debug "Handler manually set to '$handler'" 62 + fi 63 + 64 + # shellcheck disable=SC2319 65 + # shellcheck disable=SC2181 66 + if [[ -n $handler ]] || [[ $? != 0 ]]; then 67 + atfile.say.debug "Opening '$key' ($file_type) with '${handler//.desktop/}'..." 68 + 69 + # HACK: Some apps don't like http(s)://; we'll need to handle these 70 + if [[ $(atfile.handle.is_temp_file_needed "$handler" "$file_type") == 1 ]]; then 71 + atfile.say.debug "Unsupported for streaming" 72 + 73 + download_success=1 74 + # shellcheck disable=SC2154 75 + tmp_path="$_path_blobs_tmp/$blob_cid" 76 + 77 + if ! [[ -f "$tmp_path" ]]; then 78 + atfile.say.debug "Downloading '$blob_cid'..." 79 + atfile.http.download "$blob_uri" "$tmp_path" 80 + [[ $? != 0 ]] && download_success=0 81 + else 82 + atfile.say.debug "Blob '$blob_cid' already exists" 83 + fi 84 + 85 + if [[ $download_success == 1 ]]; then 86 + atfile.say.debug "Launching '$handler'..." 87 + gtk-launch "$handler" "$tmp_path" </dev/null &>/dev/null & 88 + else 89 + atfile.die.gui \ 90 + "Unable to download '$key'" 91 + fi 92 + else 93 + atfile.say.debug "Launching '$handler'..." 94 + gtk-launch "$handler" "$blob_uri" </dev/null &>/dev/null & 95 + fi 96 + else 97 + atfile.say.debug "No handler for '$file_type'. Launching URI..." 98 + atfile.util.launch_uri "$blob_uri" 99 + fi 100 + else 101 + atfile.say.debug "Relevant tools not installed. Launching URI..." 102 + atfile.util.launch_uri "$blob_uri" 103 + fi 104 + else 105 + atfile.die.gui \ 106 + "Invalid ATFile URI\nโ†ณ Must be 'atfile://<actor>/<key>'" \ 107 + "Invalid ATFile URI" 108 + fi 109 + }
+6 -4
src/commands/help.sh
··· 75 75 bsky [<actor>] 76 76 Get Bluesky profile for <actor>\n 77 77 handle <at-uri> 78 - Open at:// URI with relevant App\n 78 + Open at:// URI with PDSls\n 79 79 handle <atfile-uri> [<handler>] 80 80 Open atfile:// URI with relevant App 81 81 โ„น๏ธ Set <handler> to a .desktop entry (with '.desktop') to force the ··· 132 132 Endpoint of the PDS 133 133 โ„น๏ธ Your PDS is resolved from your username. Set to override it (or if 134 134 resolving fails) 135 + ${_envvar_prefix}_ENDPOINT_PDSLS <url> (default: ${_endpoint_pdsls_default}) 136 + Endpoint of PDSls 135 137 ${_envvar_prefix}_ENDPOINT_PLC_DIRECTORY <url> (default: ${_endpoint_plc_directory_default}$([[ $_endpoint_plc_directory_default == *"zio.blue" ]] && echo "ยฒ")) 136 138 Endpoint of the PLC directory 137 139 ${_envvar_prefix}_ENDPOINT_SOCIAL_APP <url> (default: ${_endpoint_social_app_default}) ··· 162 164 Disable periodic update checking when command finishes 163 165 ${_envvar_prefix}_DISABLE_UPDATE_COMMAND <boolยน> (default: $_disable_update_command_default) 164 166 Disable \`update\` command\n 165 - ${_envvar_prefix}_DEBUG <boolยน> (default: 0) 167 + ${_envvar_prefix}_DEBUGยณ <boolยน> (default: 0) 166 168 Print debug outputs 167 169 โš ๏ธ When output is JSON (${_envvar_prefix}_OUTPUT_JSON=1), sets to 0\n 168 170 ยน A bool in Bash is 1 (true) or 0 (false) 169 - ยฒ These servers are ran by @$handle. You can trust us!" 171 + ยฒ These servers are ran by @$handle. You can trust us! 172 + ยณ Cannot be set by config file" 170 173 171 174 usage_paths="Paths 172 175 $_path_envvar ··· 190 193 191 194 Usage 192 195 $_prog <command> [<arguments>] 193 - $_prog at://<actor>[/<collection>/<rkey>] 194 196 $_prog atfile://<actor>/<key>\n\n" 195 197 196 198 [[ $ATFILE_DEVEL == 1 ]] && usage+="$usage_commands_devel\n\n"
+12 -2
src/commands/install.sh
··· 25 25 fi 26 26 27 27 case $_os in 28 + "linux-termux") 29 + # NOTE: The correct path of '$PREFIX/local/bin' would be more correct, 30 + # however, '$PREFIX/local' doesn't exist by default on Termux (and thus, 31 + # not in $PATH), so we'll install it in '$PREFIX/bin' instead 32 + # shellcheck disable=SC2153 33 + install_dir="$PREFIX/bin" 34 + ;; 28 35 "haiku") 29 36 install_dir="/boot/system/non-packaged/bin" 30 37 ;; ··· 39 46 esac 40 47 41 48 if [[ $# -gt 0 ]]; then 42 - atfile.say.debug "Overriden variables\nโ†ณ Path: $override_path\nโ†ณ Version: $override_version\nโ†ณ DID: $override_did" 49 + atfile.say.debug "Overridden variables\nโ†ณ Path: $override_path\nโ†ณ Version: $override_version\nโ†ณ DID: $override_did" 43 50 fi 44 51 45 52 atfile.say.debug "Setting up..." 46 53 47 54 [[ -n "$override_path" ]] && install_dir="$override_path" 55 + mkdir -p "$install_dir" 48 56 mkdir -p "$conf_dir" 49 57 # shellcheck disable=SC2154 50 58 touch "$conf_dir/$_file_envvar" ··· 94 102 95 103 atfile.say.debug "Found latest version\nโ†ณ Version: $found_version ($parsed_found_version)\nโ†ณ Source: $source_did\nโ†ณ Blob: $found_version_blob" 96 104 97 - atfile.say.debug "Download '$blob_url'..." 105 + atfile.say.debug "Downloading...\nโ†ณ Source: $blob_url\nโ†ณ Dest.: ${install_dir}/$install_file" 98 106 99 107 curl -s -o "${install_dir}/$install_file" "$blob_url" 108 + # shellcheck disable=SC2181 100 109 [[ $? != 0 ]] && atfile.die "Unable to download" 101 110 102 111 atfile.say.debug "Installing...\nโ†ณ OS: $_os\nโ†ณ Install: $install_dir/$install_file\nโ†ณ Config: $conf_dir/$_file_envvar" ··· 108 117 atfile.say.debug "Creating config file..." 109 118 110 119 echo -e "ATFILE_USERNAME=<your-username>\nATFILE_PASSWORD=<your-password>" > "$conf_dir/$_file_envvar" 120 + # shellcheck disable=SC2320 111 121 [[ $? != 0 ]] && die "Unable to create config file ($conf_dir/$_file_envvar)" 112 122 fi 113 123
-172
src/commands/old_cmds.sh
··· 289 289 fi 290 290 } 291 291 292 - function atfile.invoke.handle_atfile() { 293 - uri="$1" 294 - handler="$2" 295 - 296 - function atfile.invoke.handle_atfile.is_temp_file_needed() { 297 - handler="${1//.desktop/}" 298 - type="$2" 299 - 300 - handlers=( 301 - "app.drey.EarTag" 302 - "com.github.neithern.g4music" 303 - ) 304 - 305 - if [[ ${handlers[*]} =~ $handler ]]; then 306 - echo 1 307 - elif [[ $type == "text/"* ]]; then 308 - echo 1 309 - else 310 - echo 0 311 - fi 312 - } 313 - 314 - [[ $_output_json == 1 ]] && atfile.die "Command not available as JSON" 315 - 316 - actor="$(echo "$uri" | cut -d "/" -f 3)" 317 - key="$(echo "$uri" | cut -d "/" -f 4)" 318 - 319 - if [[ -n "$actor" && -n "$key" ]]; then 320 - atfile.util.override_actor "$actor" 321 - 322 - atfile.say.debug "Getting record...\nโ†ณ NSID: $_nsid_upload\nโ†ณ Repo: $_username\nโ†ณ Key: $key" 323 - record="$(com.atproto.repo.getRecord "$_username" "$_nsid_upload" "$key")" 324 - error="$(atfile.util.get_xrpc_error $? "$record")" 325 - [[ -n "$error" ]] && atfile.die.gui.xrpc_error "Unable to get '$key'" "$error" 326 - 327 - blob_cid="$(echo "$record" | jq -r ".value.blob.ref.\"\$link\"")" 328 - blob_uri="$(atfile.util.build_blob_uri "$_username" "$blob_cid")" 329 - file_type="$(echo "$record" | jq -r '.value.file.mimeType')" 330 - 331 - if [[ $_os == "linux"* ]] && \ 332 - [ -x "$(command -v xdg-mime)" ] && \ 333 - [ -x "$(command -v xdg-open)" ] && \ 334 - [ -x "$(command -v gtk-launch)" ]; then 335 - 336 - # HACK: Open with browser if $file_type isn't set 337 - [[ -z $file_type ]] && file_type="text/html" 338 - 339 - if [[ -z $handler ]]; then 340 - atfile.say.debug "Querying for handler '$file_type'..." 341 - handler="$(xdg-mime query default "$file_type")" 342 - else 343 - handler="$handler.desktop" 344 - atfile.say.debug "Handler manually set to '$handler'" 345 - fi 346 - 347 - # shellcheck disable=SC2319 348 - # shellcheck disable=SC2181 349 - if [[ -n $handler ]] || [[ $? != 0 ]]; then 350 - atfile.say.debug "Opening '$key' ($file_type) with '${handler//.desktop/}'..." 351 - 352 - # HACK: Some apps don't like http(s)://; we'll need to handle these 353 - if [[ $(atfile.invoke.handle_atfile.is_temp_file_needed "$handler" "$file_type") == 1 ]]; then 354 - atfile.say.debug "Unsupported for streaming" 355 - 356 - download_success=1 357 - # shellcheck disable=SC2154 358 - tmp_path="$_path_blobs_tmp/$blob_cid" 359 - 360 - if ! [[ -f "$tmp_path" ]]; then 361 - atfile.say.debug "Downloading '$blob_cid'..." 362 - atfile.http.download "$blob_uri" "$tmp_path" 363 - [[ $? != 0 ]] && download_success=0 364 - else 365 - atfile.say.debug "Blob '$blob_cid' already exists" 366 - fi 367 - 368 - if [[ $download_success == 1 ]]; then 369 - atfile.say.debug "Launching '$handler'..." 370 - gtk-launch "$handler" "$tmp_path" </dev/null &>/dev/null & 371 - else 372 - atfile.die.gui \ 373 - "Unable to download '$key'" 374 - fi 375 - else 376 - atfile.say.debug "Launching '$handler'..." 377 - gtk-launch "$handler" "$blob_uri" </dev/null &>/dev/null & 378 - fi 379 - else 380 - atfile.say.debug "No handler for '$file_type'. Launching URI..." 381 - atfile.util.launch_uri "$blob_uri" 382 - fi 383 - else 384 - atfile.say.debug "Relevant tools not installed. Launching URI..." 385 - atfile.util.launch_uri "$blob_uri" 386 - fi 387 - else 388 - atfile.die.gui \ 389 - "Invalid ATFile URI\nโ†ณ Must be 'atfile://<actor>/<key>'" \ 390 - "Invalid ATFile URI" 391 - fi 392 - } 393 - 394 - function atfile.invoke.handle_aturi() { 395 - uri="$1" 396 - 397 - [[ $_output_json == 1 ]] && atfile.die "Command not available as JSON" 398 - [[ "$uri" != "at://"* ]] && atfile.die.gui \ 399 - "Invalid AT URI\nโ†ณ Must be 'at://<actor>[/<collection>/<rkey>]'" \ 400 - "Invalid AT URI" 401 - 402 - atfile.say.debug "Resolving '$uri'..." 403 - app_uri="$(atfile.util.get_app_url_for_at_uri "$uri")" 404 - [[ -z "$app_uri" ]] && atfile.die.gui \ 405 - "Unable to resolve AT URI to App" 406 - 407 - app_proto="$(echo "$app_uri" | cut -d ":" -f 1)" 408 - 409 - atfile.say.debug "Opening '$app_uri' ($app_proto)..." 410 - 411 - if [[ $app_proto == "atfile" ]]; then 412 - atfile.invoke.handle_atfile "$app_uri" 413 - else 414 - atfile.util.launch_uri "$app_uri" 415 - fi 416 - } 417 - 418 292 function atfile.invoke.list() { 419 293 cursor="$1" 420 294 unset error ··· 539 413 540 414 if [[ -n "$error" ]]; then 541 415 atfile.die "Unable to cat '$key'" "$error" 542 - fi 543 - } 544 - 545 - function atfile.invoke.toggle_desktop() { 546 - unset desktop_dir 547 - unset mime_dir 548 - 549 - [[ $_os == "haiku" ]] && atfile.die "Not available on Haiku" 550 - [[ $_os == "macos" ]] && atfile.die "Not available on macOS\nThink you could help? See: https://tangled.sh/@zio.sh/atfile/issues/9" 551 - 552 - uid="$(id -u)" 553 - if [[ $uid == 0 ]]; then 554 - desktop_dir="/usr/local/share/applications" 555 - mime_dir="/usr/local/share/mime" 556 - else 557 - desktop_dir="$HOME/.local/share/applications" 558 - mime_dir="$HOME/.local/share/mime" 559 - fi 560 - 561 - desktop_path="$desktop_dir/atfile-handler.desktop" 562 - mkdir -p "$desktop_dir" 563 - mkdir -p "$mime_dir" 564 - 565 - if [[ -f "$desktop_path" ]]; then 566 - atfile.say "Removing '$desktop_path'..." 567 - rm "$desktop_path" 568 - else 569 - atfile.say "Installing '$desktop_path'..." 570 - 571 - echo "[Desktop Entry] 572 - Name=ATFile (Handler) 573 - Description=Handle atfile:/at: URIs with ATFile 574 - Exec=$_prog_path handle %U 575 - Terminal=false 576 - Type=Application 577 - MimeType=x-scheme-handler/at;x-scheme-handler/atfile; 578 - NoDisplay=true" > "$desktop_path" 579 - fi 580 - 581 - if [ -x "$(command -v xdg-mime)" ] &&\ 582 - [ -x "$(command -v update-mime-database)" ]; then 583 - atfile.say "Updating mime database..." 584 - 585 - update-mime-database "$mime_dir" 586 - xdg-mime default atfile-handler.desktop x-scheme-handler/at 587 - xdg-mime default atfile-handler.desktop x-scheme-handler/atfile 588 416 fi 589 417 } 590 418
+2
src/commands/record.sh
··· 48 48 at_collection="$(atfile.util.parse_at_uri "$at_uri" "collection")" 49 49 at_rkey="$(atfile.util.parse_at_uri "$at_uri" "rkey")" 50 50 51 + atfile.say.debug "Resolved AT URI\nโ†ณ Actor: $at_actor\nโ†ณ Collection: $at_collection\nโ†ณ RKey: $at_rkey" 52 + 51 53 case "$sub_command" in 52 54 "create") 53 55 if [[ -z "$at_rkey" ]]; then
-186
src/commands/release.sh
··· 1 - #!/usr/bin/env bash 2 - # atfile-devel=ignore-build 3 - 4 - function atfile.release() { 5 - # shellcheck disable=SC2154 6 - [[ $_os != "linux" ]] && atfile.die "Only available on Linux (GNU)\nโ†ณ Detected OS: $_os" 7 - 8 - function atfile.release.get_devel_value() { 9 - local file="$1" 10 - local value="$2" 11 - local found_line 12 - 13 - found_line="$(grep '^# atfile-devel=' "$file" | head -n1)" 14 - if [[ -n "$found_line" ]]; then 15 - local devel_values="${found_line#*=}" 16 - IFS=',' read -ra arr <<< "$devel_values" 17 - for v in "${arr[@]}"; do 18 - if [[ "$v" == "$value" ]]; then 19 - echo 1 20 - fi 21 - done 22 - fi 23 - } 24 - 25 - function atfile.release.replace_template_var() { 26 - string="$1" 27 - key="$2" 28 - value="$3" 29 - 30 - sed -s "s|{:$key:}|$value|g" <<< "$string" 31 - } 32 - 33 - atfile.util.check_prog "git" 34 - atfile.util.check_prog "md5sum" 35 - atfile.util.check_prog "shellcheck" 36 - 37 - id="$(atfile.util.get_random 13)" 38 - commit_author="$(git config user.name) <$(git config user.email)>" 39 - commit_hash="$(git rev-parse HEAD)" 40 - commit_date="$(git show --no-patch --format=%ci "$commit_hash")" 41 - # shellcheck disable=SC2154 42 - dist_file="$(echo "$_prog" | cut -d "." -f 1)-${_version}.sh" 43 - # shellcheck disable=SC2154 44 - dist_dir="$_prog_dir/bin" 45 - dist_path="$dist_dir/$dist_file" 46 - dist_path_relative="$(realpath --relative-to="$(pwd)" "$dist_path")" 47 - parsed_version="$(atfile.util.parse_version "$_version")" 48 - version_record_id="atfile-$parsed_version" 49 - 50 - test_error_count=0 51 - test_info_count=0 52 - test_style_count=0 53 - test_warning_count=0 54 - test_ignore_count=0 55 - 56 - atfile.say "โš’๏ธ Building..." 57 - 58 - echo "โ†ณ Creating '$dist_file'..." 59 - mkdir -p "$dist_dir" 60 - echo "#!/usr/bin/env bash" > "$dist_path" 61 - 62 - echo "โ†ณ Generating header..." 63 - echo -e "\n# ATFile <${ATFILE_FORCE_META_REPO}> 64 - # --- 65 - # Version: $_version 66 - # Commit: $commit_hash 67 - # Author: $commit_author 68 - # Build: $id ($(hostname):$(atfile.util.get_os)) 69 - # --- 70 - # Psst! You can \`source atfile\` in your own Bash scripts! 71 - " >> "$dist_path" 72 - 73 - for s in "${ATFILE_DEVEL_INCLUDES[@]}" 74 - do 75 - if [[ -f "$s" ]]; then 76 - if [[ $(atfile.release.get_devel_value "$s" "ignore-build" == 1 ) ]]; then 77 - echo "โ†ณ Ignoring: $s" 78 - else 79 - echo "โ†ณ Compiling: $s" 80 - 81 - while IFS="" read -r line 82 - do 83 - include_line=1 84 - 85 - if [[ $line == "#"* ]] ||\ 86 - [[ $line == *" #"* ]] ||\ 87 - [[ $line == " " ]] ||\ 88 - [[ $line == "" ]]; then 89 - include_line=0 90 - fi 91 - 92 - if [[ $line == *"# shellcheck disable"* ]]; then 93 - if [[ $line == *"=SC2154"* ]]; then 94 - include_line=0 95 - else 96 - include_line=1 97 - (( test_ignore_count++ )) 98 - fi 99 - fi 100 - 101 - if [[ $include_line == 1 ]]; then 102 - if [[ $line == *"{:"* && $line == *":}"* ]]; then 103 - # NOTE: Not using atfile.util.get_envvar() here, as confusion can arise from config file 104 - line="$(atfile.release.replace_template_var "$line" "meta_author" "$ATFILE_FORCE_META_AUTHOR")" 105 - line="$(atfile.release.replace_template_var "$line" "meta_did" "$ATFILE_FORCE_META_DID")" 106 - line="$(atfile.release.replace_template_var "$line" "meta_repo" "$ATFILE_FORCE_META_REPO")" 107 - line="$(atfile.release.replace_template_var "$line" "meta_year" "$ATFILE_FORCE_META_YEAR")" 108 - line="$(atfile.release.replace_template_var "$line" "version" "$ATFILE_FORCE_VERSION")" 109 - fi 110 - 111 - echo "$line" >> "$dist_path" 112 - fi 113 - done < "$s" 114 - fi 115 - fi 116 - done 117 - 118 - echo -e "\n# \"Four million lines of BASIC\"\n# - Kif Kroker (3003)" >> "$dist_path" 119 - 120 - checksum="$(atfile.util.get_md5 "$dist_path" | cut -d "|" -f 1)" 121 - 122 - echo "๐Ÿงช Testing..." 123 - shellcheck_output="$(shellcheck --format=json "$dist_path" 2>&1)" 124 - 125 - while read -r item; do 126 - code="$(echo "$item" | jq -r '.code')" 127 - col="$(echo "$item" | jq -r '.column')" 128 - line="$(echo "$item" | jq -r '.line')" 129 - level="$(echo "$item" | jq -r '.level')" 130 - message="$(echo "$item" | jq -r '.message')" 131 - 132 - case "$level" in 133 - "error") level="๐Ÿ›‘ Error"; (( test_error_count++ )) ;; 134 - "info") level="โ„น๏ธ Info"; (( test_info_count++ )) ;; 135 - "style") level="๐ŸŽจ Style"; (( test_style_count++ )) ;; 136 - "warning") level="โš ๏ธ Warning"; (( test_warning_count++ )) ;; 137 - esac 138 - 139 - echo "โ†ณ $level ($line:$col): [SC$code] $message" 140 - done <<< "$(echo "$shellcheck_output" | jq -c '.[]')" 141 - 142 - test_total_count=$(( test_error_count + test_info_count + test_style_count + test_warning_count )) 143 - 144 - echo -e "---\nโœ… Built: $_version 145 - โ†ณ Path: ./$dist_path_relative 146 - โ†ณ Check: $checksum 147 - โ†ณ Size: $(atfile.util.get_file_size_pretty "$(stat -c %s "$dist_path")") 148 - โ†ณ Lines: $(atfile.util.fmt_int "$(wc -l < "$dist_path")") 149 - โ†ณ Issues: $(atfile.util.fmt_int "$test_total_count") 150 - โ†ณ Error: $(atfile.util.fmt_int "$test_error_count") 151 - โ†ณ Warning: $(atfile.util.fmt_int "$test_warning_count") 152 - โ†ณ Info: $(atfile.util.fmt_int "$test_info_count") 153 - โ†ณ Style: $(atfile.util.fmt_int "$test_style_count") 154 - โ†ณ Ignored: $(atfile.util.fmt_int "$test_ignore_count") 155 - โ†ณ ID: $id" 156 - 157 - chmod +x "$dist_path" 158 - 159 - # shellcheck disable=SC2154 160 - if [[ $_devel_enable_publish == 1 ]]; then 161 - if [[ $test_error_count -gt 0 ]]; then 162 - atfile.die "Unable to publish ($test_error_count errors detected)" 163 - fi 164 - 165 - atfile.say "---\nโœจ Updating..." 166 - atfile.auth "$_devel_dist_username" "$_devel_dist_password" 167 - [[ $_version == *"+"* ]] && atfile.die "Cannot publish a Git version ($_version)" 168 - 169 - atfile.say "โ†ณ Uploading '$dist_path'..." 170 - atfile.invoke.upload "$dist_path" "" "$version_record_id" 171 - # shellcheck disable=SC2181 172 - [[ $? != 0 ]] && atfile.die "Unable to upload '$dist_path'" 173 - 174 - latest_release_record="{ 175 - \"version\": \"$_version\", 176 - \"releasedAt\": \"$(atfile.util.get_date "$commit_date")\", 177 - \"commit\": \"$commit_hash\", 178 - \"id\": \"$id\", 179 - \"checksum\": \"$checksum\" 180 - }" 181 - 182 - atfile.say "โ†ณ Bumping current version..." 183 - # shellcheck disable=SC2154 184 - atfile.invoke.manage_record put "at://$_devel_dist_username/self.atfile.latest/self" "$latest_release_record" &> /dev/null 185 - fi 186 - }
+56 -8
src/commands/something_broke.sh
··· 19 19 function atfile.something_broke.print_prog_version() { 20 20 prog="$1" 21 21 version_arg="$2" 22 - 22 + head="$3" 23 + 24 + [[ -z "$head" ]] && head="1" 23 25 [[ -z "$version_arg" ]] && version_arg="--version" 24 26 25 27 if [ -x "$(command -v "$prog")" ]; then 26 - eval "$prog $version_arg 2>&1" 28 + version_output="$(eval "$prog $version_arg 2>&1")" 29 + if [[ $head == 0 ]]; then 30 + echo -e "$version_output" 31 + else 32 + echo -e "$version_output" | head -n "$head" | sed "s/$prog //g" 33 + fi 27 34 else 28 35 echo "$prog_not_installed_placeholder" 29 36 fi ··· 34 41 atfile.die "Command not available as JSON" 35 42 fi 36 43 44 + unset cut_version 37 45 unset md5sum_version 46 + unset sed_version 38 47 finger_record="$(atfile.util.get_finger_record 1)" 39 - mediainfo_version="$(atfile.something_broke.print_prog_version "mediainfo")" 48 + git_version="$(atfile.something_broke.print_prog_version "git")" 49 + hostname_version="$(atfile.something_broke.print_prog_version "hostname")" 50 + mediainfo_version="$(atfile.something_broke.print_prog_version "mediainfo" "--version" 0)" 40 51 41 52 # shellcheck disable=SC2154 42 53 if [[ $_os == "linux-musl" ]]; then 43 54 md5sum_version="$(atfile.something_broke.print_prog_version "md5sum" "--help")" 55 + # TODO: cut, sed 44 56 else 57 + cut_version="$(atfile.something_broke.print_prog_version "cut")" 45 58 md5sum_version="$(atfile.something_broke.print_prog_version "md5sum")" 59 + sed_version="$(atfile.something_broke.print_prog_version "sed")" 60 + fi 61 + 62 + if [[ "$cut_version" != "$prog_not_installed_placeholder" ]]; then 63 + if [[ "$cut_version" == *GNU* ]]; then 64 + cut_version="$(echo "$cut_version" | cut -d " " -f 3) (GNU)" 65 + else 66 + cut_version="(Unsupported)" 67 + fi 68 + fi 69 + 70 + if [[ "$git_version" != "$prog_not_installed_placeholder" ]]; then 71 + git_version="$(echo "$git_version" | cut -d " " -f 2)" 72 + fi 73 + 74 + if [[ "$hostname_version" != "$prog_not_installed_placeholder" ]]; then 75 + if [[ "$hostname_version" == *net-tools* ]]; then 76 + hostname_version="$(echo "$hostname_version" | cut -d " " -f 2) (net-tools)" 77 + fi 46 78 fi 47 79 48 80 if [[ "$md5sum_version" != "$prog_not_installed_placeholder" ]]; then 49 - md5sum_version="$(echo "$md5sum_version" | head -n 1)" 50 81 if [[ "$md5sum_version" == *GNU* ]]; then 51 - md5sum_version="$(echo "$md5sum_version" | cut -d " " -f 4) (GNU)" 82 + md5sum_version="$(echo "$md5sum_version" | cut -d " " -f 3) (GNU)" 52 83 elif [[ "$md5sum_version" == *BusyBox* ]]; then 53 - md5sum_version="$(echo "$md5sum_version" | cut -d " " -f 2 | cut -d "v" -f 2) (BusyBox)" 84 + md5sum_version="$(echo "$md5sum_version" | cut -d " " -f 1 | cut -d "v" -f 2) (BusyBox)" 54 85 else 55 - md5sum_version="(?)" 86 + md5sum_version="(Unsupported)" 56 87 fi 57 88 fi 58 89 59 90 if [[ "$mediainfo_version" != "$prog_not_installed_placeholder" ]]; then 60 91 mediainfo_version="$(echo "$mediainfo_version" | grep "MediaInfoLib" | cut -d "v" -f 2)" 61 92 fi 93 + 94 + if [[ "$sed_version" != "$prog_not_installed_placeholder" ]]; then 95 + if [[ "$sed_version" == *GNU* ]]; then 96 + sed_version="$(echo "$sed_version" | cut -d " " -f 3) (GNU)" 97 + else 98 + sed_version="(Unsupported)" 99 + fi 100 + fi 62 101 63 102 debug_output="ATFile 64 103 โ†ณ Version: $_version ··· 89 128 $(atfile.something_broke.print_envvar "ENDPOINT_APPVIEW" "$_endpoint_appview_default") 90 129 $(atfile.something_broke.print_envvar "ENDPOINT_JETSTREAM" "$_endpoint_jetstream_default") 91 130 $(atfile.something_broke.print_envvar "ENDPOINT_PDS") 131 + $(atfile.something_broke.print_envvar "ENDPOINT_PDSLS" "$_endpoint_pdsls_default") 92 132 $(atfile.something_broke.print_envvar "ENDPOINT_PLC_DIRECTORY" "$_endpoint_plc_directory_default") 93 133 $(atfile.something_broke.print_envvar "ENDPOINT_SOCIAL_APP" "$_endpoint_social_app_default") 94 134 $(atfile.something_broke.print_envvar "FMT_BLOB_URL" "$_fmt_blob_url_default") ··· 103 143 $(atfile.something_broke.print_envvar "MAX_LIST" "$_max_list_default") 104 144 $(atfile.something_broke.print_envvar "OUTPUT_JSON" "$_output_json_default") 105 145 $(atfile.something_broke.print_envvar "PATH_CONF" "$_path_envvar") 146 + $(atfile.something_broke.print_envvar "PATH_HOOK_POST_START") 147 + $(atfile.something_broke.print_envvar "PATH_HOOK_PRE_EXIT") 148 + $(atfile.something_broke.print_envvar "PATH_HOOK_PRE_START") 106 149 โ†ณ ${_envvar_prefix}_PASSWORD: $([[ -n $(atfile.util.get_envvar "${_envvar_prefix}_PASSWORD") ]] && echo "(Set)") 107 150 $(atfile.something_broke.print_envvar "USERNAME") 108 151 Paths ··· 113 156 โ†ณ OS: $_os ($(echo "$finger_record" | jq -r ".os")) 114 157 โ†ณ Shell: $SHELL 115 158 โ†ณ Path: $PATH 159 + โ†ณ CI: $_ci 116 160 Deps 117 161 โ†ณ Bash: $BASH_VERSION 118 - โ†ณ curl: $(atfile.something_broke.print_prog_version "curl" "--version" | head -n 1 | cut -d " " -f 2) 162 + โ†ณ curl: $(atfile.something_broke.print_prog_version "curl" "--version" | cut -d " " -f 1) 163 + โ†ณ cut: $cut_version 119 164 โ†ณ ExifTool: $(atfile.something_broke.print_prog_version "exiftool" "-ver") 165 + โ†ณ Git: $git_version 166 + โ†ณ hostname: $hostname_version 120 167 โ†ณ jq: $(atfile.something_broke.print_prog_version "jq" | sed -e "s|jq-||g") 121 168 โ†ณ md5sum: $md5sum_version 122 169 โ†ณ MediaInfo: $mediainfo_version 170 + โ†ณ sed: $sed_version 123 171 Misc. 124 172 โ†ณ Checksum: $([[ "$md5sum_version" != "$prog_not_installed_placeholder" ]] && md5sum "$_prog_path" || echo "(?)") 125 173 โ†ณ Dimensions: $(atfile.util.get_term_cols) Cols / $(atfile.util.get_term_rows) Rows
+48
src/commands/toggle-desktop.sh
··· 1 + #!/usr/bin/env bash 2 + 3 + function atfile.toggle_desktop() { 4 + unset desktop_dir 5 + unset mime_dir 6 + 7 + # shellcheck disable=SC2154 8 + [[ $_os == "haiku" ]] && atfile.die "Not available on Haiku" 9 + [[ $_os == "macos" ]] && atfile.die "Not available on macOS" 10 + 11 + uid="$(id -u)" 12 + if [[ $uid == 0 ]]; then 13 + desktop_dir="/usr/local/share/applications" 14 + mime_dir="/usr/local/share/mime" 15 + else 16 + desktop_dir="$HOME/.local/share/applications" 17 + mime_dir="$HOME/.local/share/mime" 18 + fi 19 + 20 + desktop_path="$desktop_dir/atfile-handler.desktop" 21 + mkdir -p "$desktop_dir" 22 + mkdir -p "$mime_dir" 23 + 24 + if [[ -f "$desktop_path" ]]; then 25 + atfile.say "Removing '$desktop_path'..." 26 + rm "$desktop_path" 27 + else 28 + atfile.say "Installing '$desktop_path'..." 29 + 30 + echo "[Desktop Entry] 31 + Name=ATFile (Handler) 32 + Description=Handle atfile:/at: URIs with ATFile 33 + Exec=$_prog_path handle %U 34 + Terminal=false 35 + Type=Application 36 + MimeType=x-scheme-handler/at;x-scheme-handler/atfile; 37 + NoDisplay=true" > "$desktop_path" 38 + fi 39 + 40 + if [ -x "$(command -v xdg-mime)" ] &&\ 41 + [ -x "$(command -v update-mime-database)" ]; then 42 + atfile.say "Updating mime database..." 43 + 44 + update-mime-database "$mime_dir" 45 + xdg-mime default atfile-handler.desktop x-scheme-handler/at 46 + xdg-mime default atfile-handler.desktop x-scheme-handler/atfile 47 + fi 48 + }
+1 -1
src/commands/token.sh
··· 1 1 #!/usr/bin/env bash 2 2 3 - function atfile.invoke.token() { 3 + function atfile.token() { 4 4 atfile.xrpc.pds.jwt 5 5 }
+22 -10
src/entry.sh
··· 13 13 14 14 ### Combination 15 15 16 + _ci="$(atfile.util.get_ci)" 16 17 _command="$1" 17 18 _command_args=("${@:2}") 18 19 _os="$(atfile.util.get_os)" ··· 24 25 _meta_repo="{:meta_repo:}" 25 26 _meta_year="{:meta_year:}" 26 27 _now="$(atfile.util.get_date)" 28 + _path_hook_post_start="$(atfile.util.get_envvar "${_envvar_prefix}_PATH_HOOK_POST_START")" 29 + _path_hook_pre_exit="$(atfile.util.get_envvar "${_envvar_prefix}_PATH_HOOK_PRE_EXIT")" 30 + _path_hook_pre_start="$(atfile.util.get_envvar "${_envvar_prefix}_PATH_HOOK_PRE_START")" 27 31 _version="{:version:}" 28 32 29 33 ## "Hello, world!" 30 34 31 35 atfile.say.debug "Reticulating splines..." 36 + atfile.util.source_hook "$_path_hook_pre_start" 32 37 33 38 ## Paths 34 39 ··· 50 55 _path_envvar="$_path_home/config/settings" 51 56 ;; 52 57 "linux-termux") 53 - _path_blobs_tmp="/data/data/com.termux/files/tmp" 58 + _path_blobs_tmp="$PREFIX/tmp" 54 59 ;; 55 60 "macos") 56 61 _path_envvar="$_path_home/Library/Application Support" ··· 80 85 _os_supported=1 81 86 fi 82 87 88 + ## CI detection 89 + 90 + [[ -n "$_ci" ]] && atfile.say.debug "Detected CI: $_ci" 91 + 83 92 ## Pipe detection 84 93 85 94 if [ -p /dev/stdin ] ||\ ··· 108 117 109 118 if [[ $_is_piped == 1 ]] ||\ 110 119 [[ "$1" == "install" ]]; then 120 + atfile.util.source_hook "$_path_hook_post_start" 121 + 111 122 if [[ "$1" == "install" ]]; then 112 123 atfile.install "$2" "$3" "$4" 113 124 install_exit="$?" ··· 116 127 install_exit="$?" 117 128 fi 118 129 130 + atfile.util.source_hook "$_path_hook_pre_exit" 119 131 atfile.util.print_seconds_since_start_debug 132 + 120 133 exit $install_exit 121 134 fi 122 135 ··· 152 165 _endpoint_appview_default="https://api.bsky.app" 153 166 #_endpoint_jetstream_default="wss://stream.zio.blue" 154 167 _endpoint_jetstream_default="$(atfile.util.get_random_pbc_jetstream)" 168 + _endpoint_pdsls_default="https://pdsls.dev" 155 169 _endpoint_plc_directory_default="https://plc.zio.blue" 156 170 _endpoint_social_app_default="https://bsky.app" 157 171 _fmt_blob_url_default="[server]/xrpc/com.atproto.sync.getBlob?did=[did]&cid=[cid]" ··· 178 192 _enable_update_git_clobber="$(atfile.util.get_envvar "${_envvar_prefix}_ENABLE_UPDATE_GIT_CLOBBER" "$_enable_update_git_clobber_default")" 179 193 _endpoint_appview="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_APPVIEW" "$_endpoint_appview_default")" 180 194 _endpoint_jetstream="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_JETSTREAM" "$_endpoint_jetstream_default")" 195 + _endpoint_pdsls="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_PDSLS" "$_endpoint_pdsls_default")" 181 196 _endpoint_plc_directory="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_PLC_DIRECTORY" "$_endpoint_plc_directory_default")" 182 197 _endpoint_social_app="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_SOCIAL_APP" "$_endpoint_social_app_default")" 183 198 _fmt_blob_url="$(atfile.util.get_envvar "${_envvar_prefix}_FMT_BLOB_URL" "$_fmt_blob_url_default")" ··· 201 216 _nsid_lock="${_nsid_prefix}.atfile.lock" 202 217 _nsid_meta="${_nsid_prefix}.atfile.meta" 203 218 _nsid_upload="${_nsid_prefix}.atfile.upload" 219 + _endpoint_pdsls_name="PDSls" 204 220 _endpoint_social_app_name="Bluesky" 205 221 206 222 # Setup ··· 264 280 fi 265 281 fi 266 282 267 - ## Directory creation 268 - 269 - if [[ $_disable_setup_dir_creation == 0 ]]; then 270 - atfile.util.create_dir "$_path_cache" 271 - atfile.util.create_dir "$_path_blobs_tmp" 272 - fi 273 - 274 283 ## Program detection 275 284 276 285 _prog_hint_jq="https://jqlang.github.io/jq" ··· 291 300 previous_command="$_command" 292 301 293 302 case "$_command" in 303 + "release") _command="build" ;; 294 304 "open"|"print"|"c") _command="cat" ;; 295 305 "rm") _command="delete" ;; 296 306 "download"|"f"|"d") _command="fetch" ;; ··· 299 309 "--help"|"-h") _command="help" ;; 300 310 "get"|"i") _command="info" ;; 301 311 "ls") _command="list" ;; 302 - "build") _command="release" ;; 303 312 "did") _command="resolve" ;; 304 313 "sb") _command="something-broke" ;; 305 314 "js") _command="stream" ;; 306 315 "ul"|"u") _command="upload" ;; 316 + "--update"|"-U") _command="update" ;; 307 317 "ub") _command="upload-blob" ;; 308 318 "uc") _command="upload-crypt" ;; 309 - "--update"|"-U") _command="update" ;; 310 319 "get-url"|"b") _command="url" ;; 311 320 "--version"|"-V") _command="version" ;; 312 321 esac ··· 328 337 329 338 ## Invoke 330 339 340 + atfile.util.source_hook "$_path_hook_post_start" 341 + 331 342 if [[ $_is_sourced == 0 ]]; then 332 343 atfile.auth 333 344 atfile.invoke "$_command" "${_command_args[@]}" 334 345 fi 335 346 347 + atfile.util.source_hook "$_path_hook_pre_exit" 336 348 atfile.util.print_seconds_since_start_debug
+18 -1
src/shared/cache.sh
··· 1 1 #!/usr/bin/env bash 2 2 3 + function atfile.cache.debug() { 4 + key="$1" 5 + action="$2" 6 + output="$3" 7 + 8 + [[ -z "$output" ]] && output="(Empty)" 9 + 10 + atfile.say.debug "$action '$key' cache...\nโ†ณ $output" 11 + } 12 + 3 13 function atfile.cache.del() { 4 14 key="$(atfile.util.get_cache_path "$1")" 15 + 16 + atfile.cache.debug "$1" "Deleting" 5 17 [[ -f "$key" ]] && rm "$key" 6 18 } 7 19 8 20 function atfile.cache.get() { 9 21 key="$(atfile.util.get_cache_path "$1")" 10 - [[ -f "$key" ]] && cat "$key" 22 + unset value 23 + 24 + atfile.cache.debug "$1" "Getting" "$value" 25 + [[ -f "$key" ]] && value="$(cat $key)" 26 + echo "$value" 11 27 } 12 28 13 29 function atfile.cache.set() { 14 30 key="$(atfile.util.get_cache_path "$1")" 15 31 value="$2" 16 32 33 + atfile.cache.debug "$1" "Setting" "$value" 17 34 # shellcheck disable=SC2154 18 35 mkdir -p "$_path_cache" 19 36 echo "$value" > "$key"
+3 -1
src/shared/die.sh
··· 3 3 function atfile.die() { 4 4 message="$1" 5 5 6 + # shellcheck disable=SC2154 6 7 if [[ $_output_json != 1 ]]; then 7 8 atfile.say.die "$message" 8 9 else 9 10 echo -e "{ \"error\": \"$1\" }" | jq 10 11 fi 11 12 13 + # shellcheck disable=SC2154 12 14 [[ $_is_sourced == 0 ]] && exit 255 13 15 } 14 16 ··· 50 52 51 53 function atfile.die.unknown_command() { 52 54 command="$1" 53 - atfile.die "Unknown command '$1'" 55 + atfile.die "Unknown command '$command'" 54 56 }
+17 -24
src/shared/invoke.sh
··· 5 5 shift 6 6 args=("$@") 7 7 8 + # shellcheck disable=SC2154 8 9 if [[ $_is_sourced == 0 ]] && [[ $ATFILE_DEVEL_NO_INVOKE != 1 ]]; then 9 10 atfile.say.debug "Invoking '$command'...\nโ†ณ Arguments: ${args[*]}" 10 11 ··· 25 26 atfile.bsky_profile "$_username" 26 27 else 27 28 atfile.bsky_profile "${args[0]}" 29 + fi 30 + ;; 31 + "build") 32 + if [[ $ATFILE_DEVEL == 1 ]]; then 33 + atfile.build 34 + else 35 + atfile.die.unknown_command "$command" 28 36 fi 29 37 ;; 30 38 "cat") ··· 59 67 "handle") 60 68 uri="${args[0]}" 61 69 protocol="$(atfile.util.get_uri_segment "$uri" protocol)" 62 - 63 - if [[ $protocol == "https" ]]; then 64 - http_uri="$uri" 65 - uri="$(atfile.util.map_http_to_at "$http_uri")" 66 - 67 - atfile.say.debug "Mapping '$http_uri'..." 68 - 69 - if [[ -z "$uri" ]]; then 70 - atfile.die "Unable to map '$http_uri' to at:// URI" 71 - else 72 - protocol="$(atfile.util.get_uri_segment "$uri" protocol)" 73 - fi 74 - fi 75 70 76 71 atfile.say.debug "Handling protocol '$protocol://'..." 77 72 78 73 case $protocol in 79 - "at") atfile.invoke.handle_aturi "$uri" ;; 80 - "atfile") atfile.invoke.handle_atfile "$uri" "${args[1]}" ;; 74 + "at") 75 + atfile.say.debug "Launching '$uri' in PDSls ($_endpoint_pdsls)..." 76 + atfile.util.launch_uri "$_endpoint_pdsls/$uri" 77 + ;; 78 + "atfile") 79 + atfile.handle "$uri" "${args[1]}" 80 + ;; 81 81 esac 82 82 ;; 83 83 "help") ··· 129 129 *) atfile.die.unknown_command "$(echo "$command ${args[0]}" | xargs)" ;; 130 130 esac 131 131 ;; 132 - "release") 133 - if [[ $ATFILE_DEVEL == 1 ]]; then 134 - atfile.release 135 - else 136 - atfile.die.unknown_command "$command" 137 - fi 138 - ;; 139 132 "resolve") 140 133 atfile.resolve "${args[0]}" 141 134 ;; ··· 146 139 atfile.stream "${args[0]}" "${args[1]}" "${args[2]}" "${args[3]}" 147 140 ;; 148 141 "token") 149 - atfile.invoke.token 142 + atfile.token 150 143 ;; 151 144 "toggle-mime") 152 - atfile.invoke.toggle_desktop 145 + atfile.toggle_desktop 153 146 ;; 154 147 "upload") 155 148 atfile.util.check_prog_optional_metadata
+11 -1
src/shared/say.sh
··· 10 10 11 11 prefix_length=0 12 12 13 + if [[ -n $_ci ]]; then 14 + unset color_prefix 15 + unset color_message 16 + unset color_prefix_message 17 + fi 18 + 13 19 # shellcheck disable=SC2154 14 20 if [[ $_os == "haiku" ]]; then 15 21 message="${message//โ†ณ/>}" ··· 42 48 fi 43 49 44 50 message="${message//\\n/\\n$(atfile.util.repeat_char " " "$prefix_length")}" 51 + message="${prefix}${color_message}$message\033[0m${suffix}" 52 + 53 + [[ -n "$_ci" ]] && message="${message//\\033[0m/}" 45 54 46 - echo -n -e "${prefix}${color_message}$message\033[0m${suffix}" 55 + echo -n -e "$message" 47 56 } 48 57 49 58 function atfile.say.debug() { ··· 52 61 53 62 [[ -z "$prefix" ]] && prefix="Debug" 54 63 64 + # shellcheck disable=SC2154 55 65 if [[ $_debug == 1 ]]; then 56 66 atfile.say "$message" "$prefix" 35 >&2 57 67 fi
+21 -127
src/shared/util.sh
··· 12 12 key="$1" 13 13 name="$2" 14 14 15 + # shellcheck disable=SC2154 15 16 echo "$_fmt_out_file" | sed -e "s|\[name\]|$name|g" -e "s|\[key\]|$key|g" 16 17 } 17 18 ··· 85 86 printf "%'d\n" "$1" 86 87 } 87 88 88 - # TODO: Check if record actually exists 89 - function atfile.util.get_app_url_for_at_uri() { 90 - uri="$1" 91 - 92 - actor="$(echo "$uri" | cut -d / -f 3)" 93 - collection="$(echo "$uri" | cut -d / -f 4)" 94 - rkey="$(echo "$uri" | cut -d / -f 5)" 95 - 96 - ignore_url_validation=0 97 - resolved_actor="$(atfile.util.resolve_identity "$actor")" 98 - error="$(atfile.util.get_xrpc_error $? "$resolved_actor")" 99 - [[ -n "$error" ]] && atfile.die.xrpc_error "Unable to resolve '$actor'" "$resolved_actor" 100 - 101 - unset actor_handle 102 - unset actor_pds 103 - unset resolved_url 104 - 105 - # shellcheck disable=SC2181 106 - if [[ $? == 0 ]]; then 107 - actor="$(echo "$resolved_actor" | cut -d "|" -f 1)" 108 - actor_handle="$(echo "$resolved_actor" | cut -d "|" -f 3 | cut -d "/" -f 3)" 109 - actor_pds="$(echo "$resolved_actor" | cut -d "|" -f 2)" 110 - else 111 - unset actor 112 - fi 113 - 114 - [[ -z "$rkey" ]] && rkey="self" 115 - 116 - if [[ -n "$actor" && -n "$collection" && -n "$rkey" ]]; then 117 - case "$collection" in 118 - "app.bsky.actor.profile") resolved_url="$_endpoint_social_app/profile/$actor" ;; 119 - "app.bsky.feed.generator") resolved_url="$_endpoint_social_app/profile/$actor/feed/$rkey" ;; 120 - "app.bsky.graph.list") resolved_url="$_endpoint_social_app/profile/$actor/lists/$rkey" ;; 121 - "app.bsky.graph.starterpack") resolved_url="$_endpoint_social_app/starter-pack/$actor/$rkey" ;; 122 - "app.bsky.feed.post") resolved_url="$_endpoint_social_app/profile/$actor/post/$rkey" ;; 123 - "blue.linkat.board") resolved_url="https://linkat.blue/$actor_handle" ;; 124 - "blue.zio.atfile.upload") ignore_url_validation=1 && resolved_url="atfile://$actor/$rkey" ;; 125 - "chat.bsky.actor.declaration") resolved_url="$_endpoint_social_app/messages/settings" ;; 126 - "com.shinolabs.pinksea.oekaki") resolved_url="https://pinksea.art/$actor/oekaki/$rkey" ;; 127 - "com.whtwnd.blog.entry") resolved_url="https://whtwnd.com/$actor/$rkey" ;; 128 - "events.smokesignal.app.profile") resolved_url="https://smokesignal.events/$actor" ;; 129 - "events.smokesignal.calendar.event") resolved_url="https://smokesignal.events/$actor/$rkey" ;; 130 - "fyi.unravel.frontpage.post") resolved_url="https://frontpage.fyi/post/$actor/$rkey" ;; 131 - "link.pastesphere.snippet") resolved_url="https://pastesphere.link/user/$actor/snippet/$rkey" ;; 132 - "app.bsky.feed.like"| \ 133 - "app.bsky.feed.postgate"| \ 134 - "app.bsky.feed.repost"| \ 135 - "app.bsky.feed.threadgate"| \ 136 - "app.bsky.graph.follow"| \ 137 - "app.bsky.graph.listblock"| \ 138 - "app.bsky.graph.listitem"| \ 139 - "events.smokesignal.calendar.rsvp"| \ 140 - "fyi.unravel.frontpage.comment"| \ 141 - "fyi.unravel.frontpage.vote") 142 - record="$(atfile.xrpc.pds.get "com.atproto.repo.getRecord" "repo=$actor&collection=$collection&rkey=$rkey" "" "$actor_pds")" 143 - 144 - if [[ -z "$(atfile.util.get_xrpc_error $? "$record")" ]]; then 145 - case "$collection" in 146 - "app.bsky.feed.like") 147 - resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject.uri')")" ;; 148 - "app.bsky.feed.postgate") 149 - resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.post')")" ;; 150 - "app.bsky.feed.repost") 151 - resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject.uri')")" ;; 152 - "app.bsky.feed.threadgate") 153 - resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.post')")" ;; 154 - "app.bsky.graph.follow") 155 - resolved_url="$_endpoint_social_app/profile/$(echo "$record" | jq -r '.value.subject')" ;; 156 - "app.bsky.graph.listblock") 157 - resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject')")" ;; 158 - "app.bsky.graph.listitem") 159 - resolved_url="$_endpoint_social_app/profile/$(echo "$record" | jq -r '.value.subject')" ;; 160 - "events.smokesignal.calendar.rsvp") 161 - resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject.uri')")" ;; 162 - "fyi.unravel.frontpage.comment") 163 - resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.post.uri')")/$actor/$rkey" ;; 164 - "fyi.unravel.frontpage.vote") 165 - resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject.uri')")" ;; 166 - esac 167 - fi 168 - ;; 169 - esac 170 - elif [[ -n "$actor" ]]; then 171 - resolved_url="https://pdsls.dev/at://$actor" 172 - fi 173 - 174 - if [[ -n "$resolved_url" && $ignore_url_validation == 0 ]]; then 175 - if [[ $(atfile.util.is_url_okay "$resolved_url") == 0 ]]; then 176 - unset resolved_url 177 - fi 178 - fi 179 - 180 - echo "$resolved_url" 181 - } 182 - 183 89 function atfile.util.get_cache_path() { 90 + # shellcheck disable=SC2154 91 + mkdir -p "$_path_cache" 184 92 # shellcheck disable=SC2154 185 93 echo "$_path_cache/$1" 186 94 } ··· 197 105 esac 198 106 199 107 echo "$cdn_uri" 108 + } 109 + 110 + function atfile.util.get_ci() { 111 + [[ -d "/tangled/workspace" ]] && echo "tangled" 200 112 } 201 113 202 114 # TODO: Support BusyBox's shit `date` command ··· 936 848 esac 937 849 } 938 850 939 - function atfile.util.map_http_to_at() { 940 - http_uri="$1" 941 - unset at_uri 942 - unset actor 943 - unset collection 944 - unset rkey 945 - 946 - case "$(atfile.util.get_uri_segment "$http_uri" host)" in 947 - "atproto-browser.vercel.app"|\ 948 - "pdsls.dev"|\ 949 - "pdsls.pages.dev") 950 - actor="$(atfile.util.get_uri_segment "$http_uri" 6)" 951 - collection="$(atfile.util.get_uri_segment "$http_uri" 7)" 952 - rkey="$(atfile.util.get_uri_segment "$http_uri" 8)" 953 - ;; 954 - esac 955 - 956 - if [[ -n "$actor" ]]; then 957 - at_uri="at://$actor" 958 - 959 - if [[ -n "$collection" ]]; then 960 - at_uri="$at_uri/$collection" 961 - 962 - if [[ -n "$rkey" ]]; then 963 - at_uri="$at_uri/$rkey" 964 - fi 965 - fi 966 - fi 967 - 968 - echo "$at_uri" 969 - } 970 - 971 851 # HACK: This essentially breaks the entire session (it overrides $_username and 972 852 # $_server). If sourcing, use atfile.util.override_actor_reset() to 973 853 # reset ··· 1121 1001 else 1122 1002 echo "$error" 1123 1003 exit 255 1004 + fi 1005 + } 1006 + 1007 + function atfile.util.source_hook() { 1008 + file="$1" 1009 + 1010 + if [[ -n "$file" ]]; then 1011 + atfile.say.debug "Sourcing: $file" 1012 + if [[ -f "$file" ]]; then 1013 + # shellcheck disable=SC1090 1014 + . "$file" 1015 + else 1016 + atfile.die "Unable to source '$file'" 1017 + fi 1124 1018 fi 1125 1019 } 1126 1020