mirror of
https://github.com/nushell/nushell
synced 2024-11-10 07:04:13 +00:00
REFACTOR: clean the root of the repo (#9231)
# Description i've almost always wanted to clean up the root of the repo, so here is my take at it, with some important advice given by @fdncred 😌 - `README.release.txt` is now gone and directly inline in the `release-pkg` script used in the `release` *workflow* - `build.rs` has been moved to `scripts/` and its path has been changed in [`Cargo.toml`](https://github.com/amtoine/nushell/blob/refactor/clean-root/Cargo.toml#L3) according to the [*Build Scripts* section](https://doc.rust-lang.org/cargo/reference/build-scripts.html#build-scripts) of *The Cargo Book* - i've merged `images/` into `assets/` and fix the only mention to the GIF in the README - i've moved the `docs/README.md` inside the main `README.md` as a new [*Configuration* section](https://github.com/amtoine/nushell/tree/refactor/clean-root#configuration) - the very deprecated `pkg_mgrs/` has been removed - all the `.nu`, `.sh`, `.ps1` and `.cmd` scripts have been moved to `scripts/` ### things i've left as-is - all the other `.md` documents - the configuration files - all the Rust and core stuff - `docker/` - `toolkit.nu` - the `wix/` diretory which appears to be important for `winget` # User-Facing Changes scripts that used to rely on the paths to some of the scripts should now call the scripts inside `scripts/` => i think this for the greater good, it was not pretty nor scalable to have a bunch of scripts in the root of our main `nushell` 😱 *i even think we might want to move these scripts outside the main `nushell` repo* maybe to `nu_scripts` or some other tool 👍 # Tests + Formatting - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - ⚫ `toolkit test` - ⚫ `toolkit test stdlib` # After Submitting ``` $nothing ```
This commit is contained in:
parent
4b9f479e5c
commit
8eece32a8d
20 changed files with 180 additions and 131 deletions
4
.github/workflows/release-pkg.nu
vendored
4
.github/workflows/release-pkg.nu
vendored
|
@ -122,7 +122,9 @@ print $'(char nl)All executable files:'; hr-line
|
||||||
print (ls -f $executable); sleep 1sec
|
print (ls -f $executable); sleep 1sec
|
||||||
|
|
||||||
print $'(char nl)Copying release files...'; hr-line
|
print $'(char nl)Copying release files...'; hr-line
|
||||||
cp -v README.release.txt $'($dist)/README.txt'
|
"To use Nu plugins, use the register command to tell Nu where to find the plugin. For example:
|
||||||
|
|
||||||
|
> register ./nu_plugin_query" | save $'($dist)/README.txt'
|
||||||
[LICENSE $executable] | each {|it| cp -rv $it $dist } | flatten
|
[LICENSE $executable] | each {|it| cp -rv $it $dist } | flatten
|
||||||
# Sleep a few seconds to make sure the cp process finished successfully
|
# Sleep a few seconds to make sure the cp process finished successfully
|
||||||
sleep 3sec
|
sleep 3sec
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
authors = ["The Nushell Project Developers"]
|
authors = ["The Nushell Project Developers"]
|
||||||
|
build = "scripts/build.rs"
|
||||||
default-run = "nu"
|
default-run = "nu"
|
||||||
description = "A new type of shell"
|
description = "A new type of shell"
|
||||||
documentation = "https://www.nushell.sh/book/"
|
documentation = "https://www.nushell.sh/book/"
|
||||||
|
|
19
README.md
19
README.md
|
@ -10,13 +10,14 @@
|
||||||
|
|
||||||
A new type of shell.
|
A new type of shell.
|
||||||
|
|
||||||
![Example of nushell](images/nushell-autocomplete6.gif "Example of nushell")
|
![Example of nushell](assets/nushell-autocomplete6.gif "Example of nushell")
|
||||||
|
|
||||||
## Table of Contents <!-- omit in toc -->
|
## Table of Contents <!-- omit in toc -->
|
||||||
|
|
||||||
- [Status](#status)
|
- [Status](#status)
|
||||||
- [Learning About Nu](#learning-about-nu)
|
- [Learning About Nu](#learning-about-nu)
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
|
- [Configuration](#configuration)
|
||||||
- [Philosophy](#philosophy)
|
- [Philosophy](#philosophy)
|
||||||
- [Pipelines](#pipelines)
|
- [Pipelines](#pipelines)
|
||||||
- [Opening files](#opening-files)
|
- [Opening files](#opening-files)
|
||||||
|
@ -55,6 +56,22 @@ Detailed installation instructions can be found in the [installation chapter of
|
||||||
[![Packaging status](https://repology.org/badge/vertical-allrepos/nushell.svg)](https://repology.org/project/nushell/versions)
|
[![Packaging status](https://repology.org/badge/vertical-allrepos/nushell.svg)](https://repology.org/project/nushell/versions)
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The default configurations can be found at [sample_config](crates/nu-utils/src/sample_config)
|
||||||
|
which are the configuration files one gets when they startup Nushell for the first time.
|
||||||
|
|
||||||
|
It sets all of the default configuration to run Nushell. From here one can
|
||||||
|
then customize this file for their specific needs.
|
||||||
|
|
||||||
|
To see where *config.nu* is located on your system simply type this command.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
$nu.config-path
|
||||||
|
```
|
||||||
|
|
||||||
|
Please see our [book](https://www.nushell.sh) for all of the Nushell documentation.
|
||||||
|
|
||||||
|
|
||||||
## Philosophy
|
## Philosophy
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
To use Nu plugins, use the register command to tell Nu where to find the plugin. For example:
|
|
||||||
|
|
||||||
> register ./nu_plugin_query
|
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
25
build-all.nu
25
build-all.nu
|
@ -1,25 +0,0 @@
|
||||||
echo '-------------------------------------------------------------------'
|
|
||||||
echo 'Building nushell (nu) with dataframes and all the plugins'
|
|
||||||
echo '-------------------------------------------------------------------'
|
|
||||||
|
|
||||||
echo $'(char nl)Building nushell'
|
|
||||||
echo '----------------------------'
|
|
||||||
cargo build --features=dataframe
|
|
||||||
|
|
||||||
let plugins = [
|
|
||||||
nu_plugin_inc,
|
|
||||||
nu_plugin_gstat,
|
|
||||||
nu_plugin_query,
|
|
||||||
nu_plugin_example,
|
|
||||||
nu_plugin_custom_values,
|
|
||||||
nu_plugin_formats,
|
|
||||||
]
|
|
||||||
|
|
||||||
for plugin in $plugins {
|
|
||||||
$'(char nl)Building ($plugin)'
|
|
||||||
'----------------------------'
|
|
||||||
cd $'crates/($plugin)'
|
|
||||||
cargo build
|
|
||||||
cd ../../
|
|
||||||
ignore
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
#!/usr/bin/env nu
|
|
||||||
|
|
||||||
let start = (date now)
|
|
||||||
# Script to generate coverage locally
|
|
||||||
#
|
|
||||||
# Output: `lcov.info` file
|
|
||||||
#
|
|
||||||
# Relies on `cargo-llvm-cov`. Install via `cargo install cargo-llvm-cov`
|
|
||||||
# https://github.com/taiki-e/cargo-llvm-cov
|
|
||||||
|
|
||||||
# You probably have to run `cargo llvm-cov clean` once manually,
|
|
||||||
# as you have to confirm to install additional tooling for your rustup toolchain.
|
|
||||||
# Else the script might stall waiting for your `y<ENTER>`
|
|
||||||
|
|
||||||
# Some of the internal tests rely on the exact cargo profile
|
|
||||||
# (This is somewhat criminal itself)
|
|
||||||
# but we have to signal to the tests that we use the `ci` `--profile`
|
|
||||||
let-env NUSHELL_CARGO_TARGET = "ci"
|
|
||||||
|
|
||||||
# Manual gathering of coverage to catch invocation of the `nu` binary.
|
|
||||||
# This is relevant for tests using the `nu!` macro from `nu-test-support`
|
|
||||||
# see: https://github.com/taiki-e/cargo-llvm-cov#get-coverage-of-external-tests
|
|
||||||
|
|
||||||
print "Setting up environment variables for coverage"
|
|
||||||
# Enable LLVM coverage tracking through environment variables
|
|
||||||
# show env outputs .ini/.toml style description of the variables
|
|
||||||
# In order to use from toml, we need to make sure our string literals are single quoted
|
|
||||||
# This is especially important when running on Windows since "C:\blah" is treated as an escape
|
|
||||||
cargo llvm-cov show-env | str replace (char dq) (char sq) -a | from toml | load-env
|
|
||||||
|
|
||||||
print "Cleaning up coverage data"
|
|
||||||
cargo llvm-cov clean --workspace
|
|
||||||
|
|
||||||
print "Building with workspace and profile=ci"
|
|
||||||
# Apparently we need to explicitly build the necessary parts
|
|
||||||
# using the `--profile=ci` is basically `debug` build with unnecessary symbols stripped
|
|
||||||
# leads to smaller binaries and potential savings when compiling and running
|
|
||||||
cargo build --workspace --profile=ci
|
|
||||||
|
|
||||||
print "Running tests with --workspace and profile=ci"
|
|
||||||
cargo test --workspace --profile=ci
|
|
||||||
|
|
||||||
# You need to provide the used profile to find the raw data
|
|
||||||
print "Generating coverage report as lcov.info"
|
|
||||||
cargo llvm-cov report --lcov --output-path lcov.info --profile=ci
|
|
||||||
|
|
||||||
let end = (date now)
|
|
||||||
$"Coverage generation took ($end - $start)."
|
|
||||||
|
|
||||||
# To display the coverage in your editor see:
|
|
||||||
#
|
|
||||||
# - https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters
|
|
||||||
# - https://github.com/umaumax/vim-lcov
|
|
||||||
# - https://github.com/andythigpen/nvim-coverage (probably needs some additional config)
|
|
|
@ -1,15 +0,0 @@
|
||||||
# Documentation
|
|
||||||
|
|
||||||
The default configurations can be found at [sample_config](../crates/nu-utils/src/sample_config)
|
|
||||||
which are the configuration files one gets when they startup Nushell for the first time.
|
|
||||||
|
|
||||||
It sets all of the default configuration to run Nushell. From here one can
|
|
||||||
then customize this file for their specific needs.
|
|
||||||
|
|
||||||
To see where *config.nu* is located on your system simply type this command.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
$nu.config-path
|
|
||||||
```
|
|
||||||
|
|
||||||
Please see our [book](https://www.nushell.sh) for all of the Nushell documentation.
|
|
|
@ -1,16 +0,0 @@
|
||||||
Id: Nushell.Nushell
|
|
||||||
Publisher: Nushell
|
|
||||||
Name: Nushell
|
|
||||||
Version: 0.17.0
|
|
||||||
License: MIT
|
|
||||||
LicenseUrl: https://github.com/nushell/nushell/blob/main/LICENSE
|
|
||||||
AppMoniker: nushell
|
|
||||||
Tags: shell, nu, nushell, functional, data, analysis
|
|
||||||
Description: Nushell. A new type of shell.
|
|
||||||
Homepage: https://www.nushell.sh/
|
|
||||||
InstallerType: msi
|
|
||||||
Installers:
|
|
||||||
- Arch: x64
|
|
||||||
Url: https://github.com/nushell/nushell/releases/download/0.17.0/nu_0_17_0_windows.msi
|
|
||||||
Sha256: 3EF3FCE4069510AD78577DC61E29F3DC02F4A384DE5E2CCD9D9862FC7E4D849E
|
|
||||||
ManifestVersion: 0.1.0
|
|
27
scripts/README.md
Normal file
27
scripts/README.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
## run the scripts
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
> the following table must be read as follows:
|
||||||
|
> - an `x` means *it works*
|
||||||
|
> - a `?` means *no data available*
|
||||||
|
>
|
||||||
|
> `.nu` scripts must be run as `nu .../foo.nu`
|
||||||
|
> `.sh` scripts must be run as `./.../foo.sh`
|
||||||
|
> `.ps1` scripts must be run as `powershell .../foo.ps1`
|
||||||
|
>
|
||||||
|
> let's say a script is called `foo`
|
||||||
|
> - an `x` in the *`./scripts`* column means *`foo` can be run from `./scripts`*
|
||||||
|
> - an `x` in the *root* column means *`foo` can be run from the root of `nushell`*
|
||||||
|
> - an `x` in the *anywhere* column means *`foo` can be run from anywhere!*
|
||||||
|
|
||||||
|
| script | `./scripts/` | root | anywhere |
|
||||||
|
| ----------------------- | ------------ | ---- | -------- |
|
||||||
|
| `build-all-maclin.sh` | x | x | x |
|
||||||
|
| `build-all-windows.cmd` | ? | x | ? |
|
||||||
|
| `build-all.nu` | x | x | x |
|
||||||
|
| `coverage-local.nu` | x | x | x |
|
||||||
|
| `coverage-local.sh` | x | x | x |
|
||||||
|
| `install-all.ps1` | ? | x | ? |
|
||||||
|
| `install-all.sh` | x | x | x |
|
||||||
|
| `register-plugins.nu` | x | x | x |
|
||||||
|
| `uninstall-all.sh` | x | x | x |
|
|
@ -1,6 +1,10 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
DIR=$(readlink -f $(dirname "${BASH_SOURCE[0]}"))
|
||||||
|
REPO_ROOT=$(dirname $DIR)
|
||||||
|
|
||||||
echo "---------------------------------------------------------------"
|
echo "---------------------------------------------------------------"
|
||||||
echo "Building nushell (nu) with dataframes and all the plugins"
|
echo "Building nushell (nu) with dataframes and all the plugins"
|
||||||
echo "---------------------------------------------------------------"
|
echo "---------------------------------------------------------------"
|
||||||
|
@ -15,11 +19,17 @@ NU_PLUGINS=(
|
||||||
)
|
)
|
||||||
|
|
||||||
echo "Building nushell"
|
echo "Building nushell"
|
||||||
|
(
|
||||||
|
cd $REPO_ROOT
|
||||||
cargo build --features=dataframe
|
cargo build --features=dataframe
|
||||||
|
)
|
||||||
|
|
||||||
for plugin in "${NU_PLUGINS[@]}"
|
for plugin in "${NU_PLUGINS[@]}"
|
||||||
do
|
do
|
||||||
echo '' && cd crates/"$plugin"
|
|
||||||
echo "Building $plugin..."
|
echo "Building $plugin..."
|
||||||
echo "-----------------------------"
|
echo "-----------------------------"
|
||||||
cargo build && cd ../..
|
(
|
||||||
|
cd "$REPO_ROOT/crates/$plugin"
|
||||||
|
cargo build
|
||||||
|
)
|
||||||
done
|
done
|
36
scripts/build-all.nu
Normal file
36
scripts/build-all.nu
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
print '-------------------------------------------------------------------'
|
||||||
|
print 'Building nushell (nu) with dataframes and all the plugins'
|
||||||
|
print '-------------------------------------------------------------------'
|
||||||
|
|
||||||
|
let repo_root = ($env.CURRENT_FILE | path dirname -n 2)
|
||||||
|
|
||||||
|
def build-nushell [] {
|
||||||
|
print $'(char nl)Building nushell'
|
||||||
|
print '----------------------------'
|
||||||
|
|
||||||
|
cd $repo_root
|
||||||
|
cargo build --features=dataframe
|
||||||
|
}
|
||||||
|
|
||||||
|
def build-plugin [] {
|
||||||
|
let plugin = $in
|
||||||
|
|
||||||
|
print $'(char nl)Building ($plugin)'
|
||||||
|
print '----------------------------'
|
||||||
|
|
||||||
|
cd $'($repo_root)/crates/($plugin)'
|
||||||
|
cargo build
|
||||||
|
}
|
||||||
|
|
||||||
|
let plugins = [
|
||||||
|
nu_plugin_inc,
|
||||||
|
nu_plugin_gstat,
|
||||||
|
nu_plugin_query,
|
||||||
|
nu_plugin_example,
|
||||||
|
nu_plugin_custom_values,
|
||||||
|
nu_plugin_formats,
|
||||||
|
]
|
||||||
|
|
||||||
|
for plugin in $plugins {
|
||||||
|
$plugin | build-plugin
|
||||||
|
}
|
60
scripts/coverage-local.nu
Executable file
60
scripts/coverage-local.nu
Executable file
|
@ -0,0 +1,60 @@
|
||||||
|
#!/usr/bin/env nu
|
||||||
|
|
||||||
|
def compute-coverage [] {
|
||||||
|
cd ($env.CURRENT_FILE | path dirname -n 2)
|
||||||
|
|
||||||
|
print "Setting up environment variables for coverage"
|
||||||
|
# Enable LLVM coverage tracking through environment variables
|
||||||
|
# show env outputs .ini/.toml style description of the variables
|
||||||
|
# In order to use from toml, we need to make sure our string literals are single quoted
|
||||||
|
# This is especially important when running on Windows since "C:\blah" is treated as an escape
|
||||||
|
cargo llvm-cov show-env | str replace (char dq) (char sq) -a | from toml | load-env
|
||||||
|
|
||||||
|
print "Cleaning up coverage data"
|
||||||
|
cargo llvm-cov clean --workspace
|
||||||
|
|
||||||
|
print "Building with workspace and profile=ci"
|
||||||
|
# Apparently we need to explicitly build the necessary parts
|
||||||
|
# using the `--profile=ci` is basically `debug` build with unnecessary symbols stripped
|
||||||
|
# leads to smaller binaries and potential savings when compiling and running
|
||||||
|
cargo build --workspace --profile=ci
|
||||||
|
|
||||||
|
print "Running tests with --workspace and profile=ci"
|
||||||
|
cargo test --workspace --profile=ci
|
||||||
|
|
||||||
|
# You need to provide the used profile to find the raw data
|
||||||
|
print "Generating coverage report as lcov.info"
|
||||||
|
cargo llvm-cov report --lcov --output-path lcov.info --profile=ci
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = (date now)
|
||||||
|
# Script to generate coverage locally
|
||||||
|
#
|
||||||
|
# Output: `lcov.info` file
|
||||||
|
#
|
||||||
|
# Relies on `cargo-llvm-cov`. Install via `cargo install cargo-llvm-cov`
|
||||||
|
# https://github.com/taiki-e/cargo-llvm-cov
|
||||||
|
|
||||||
|
# You probably have to run `cargo llvm-cov clean` once manually,
|
||||||
|
# as you have to confirm to install additional tooling for your rustup toolchain.
|
||||||
|
# Else the script might stall waiting for your `y<ENTER>`
|
||||||
|
|
||||||
|
# Some of the internal tests rely on the exact cargo profile
|
||||||
|
# (This is somewhat criminal itself)
|
||||||
|
# but we have to signal to the tests that we use the `ci` `--profile`
|
||||||
|
let-env NUSHELL_CARGO_TARGET = "ci"
|
||||||
|
|
||||||
|
# Manual gathering of coverage to catch invocation of the `nu` binary.
|
||||||
|
# This is relevant for tests using the `nu!` macro from `nu-test-support`
|
||||||
|
# see: https://github.com/taiki-e/cargo-llvm-cov#get-coverage-of-external-tests
|
||||||
|
|
||||||
|
compute-coverage
|
||||||
|
|
||||||
|
let end = (date now)
|
||||||
|
print $"Coverage generation took ($end - $start)."
|
||||||
|
|
||||||
|
# To display the coverage in your editor see:
|
||||||
|
#
|
||||||
|
# - https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters
|
||||||
|
# - https://github.com/umaumax/vim-lcov
|
||||||
|
# - https://github.com/andythigpen/nvim-coverage (probably needs some additional config)
|
|
@ -1,5 +1,8 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
DIR=$(readlink -f $(dirname "${BASH_SOURCE[0]}"))
|
||||||
|
REPO_ROOT=$(dirname $DIR)
|
||||||
|
|
||||||
# Script to generate coverage locally
|
# Script to generate coverage locally
|
||||||
#
|
#
|
||||||
# Output: `lcov.info` file
|
# Output: `lcov.info` file
|
||||||
|
@ -20,6 +23,8 @@ export NUSHELL_CARGO_TARGET=ci
|
||||||
# This is relevant for tests using the `nu!` macro from `nu-test-support`
|
# This is relevant for tests using the `nu!` macro from `nu-test-support`
|
||||||
# see: https://github.com/taiki-e/cargo-llvm-cov#get-coverage-of-external-tests
|
# see: https://github.com/taiki-e/cargo-llvm-cov#get-coverage-of-external-tests
|
||||||
|
|
||||||
|
(
|
||||||
|
cd $REPO_ROOT
|
||||||
# Enable LLVM coverage tracking through environment variables
|
# Enable LLVM coverage tracking through environment variables
|
||||||
source <(cargo llvm-cov show-env --export-prefix)
|
source <(cargo llvm-cov show-env --export-prefix)
|
||||||
cargo llvm-cov clean --workspace
|
cargo llvm-cov clean --workspace
|
||||||
|
@ -30,6 +35,7 @@ cargo build --workspace --profile=ci
|
||||||
cargo test --workspace --profile=ci
|
cargo test --workspace --profile=ci
|
||||||
# You need to provide the used profile to find the raw data
|
# You need to provide the used profile to find the raw data
|
||||||
cargo llvm-cov report --lcov --output-path lcov.info --profile=ci
|
cargo llvm-cov report --lcov --output-path lcov.info --profile=ci
|
||||||
|
)
|
||||||
|
|
||||||
# To display the coverage in your editor see:
|
# To display the coverage in your editor see:
|
||||||
#
|
#
|
|
@ -1,7 +1,10 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Usage: Just run `./install-all.sh` in nushell root directory
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
DIR=$(readlink -f $(dirname "${BASH_SOURCE[0]}"))
|
||||||
|
REPO_ROOT=$(dirname $DIR)
|
||||||
|
|
||||||
echo "-----------------------------------------------------------------"
|
echo "-----------------------------------------------------------------"
|
||||||
echo "Installing nushell (nu) with dataframes and all the plugins"
|
echo "Installing nushell (nu) with dataframes and all the plugins"
|
||||||
echo "-----------------------------------------------------------------"
|
echo "-----------------------------------------------------------------"
|
||||||
|
@ -9,7 +12,7 @@ echo ""
|
||||||
|
|
||||||
echo "Install nushell from local..."
|
echo "Install nushell from local..."
|
||||||
echo "----------------------------------------------"
|
echo "----------------------------------------------"
|
||||||
cargo install --force --path . --features=dataframe
|
cargo install --force --path "$REPO_ROOT" --features=dataframe
|
||||||
|
|
||||||
NU_PLUGINS=(
|
NU_PLUGINS=(
|
||||||
'nu_plugin_inc'
|
'nu_plugin_inc'
|
||||||
|
@ -26,5 +29,5 @@ do
|
||||||
echo "----------------------------------------------"
|
echo "----------------------------------------------"
|
||||||
echo "Install plugin $plugin from local..."
|
echo "Install plugin $plugin from local..."
|
||||||
echo "----------------------------------------------"
|
echo "----------------------------------------------"
|
||||||
cd crates/"$plugin" && cargo install --force --path . && cd ../../
|
cargo install --force --path "$REPO_ROOT/crates/$plugin"
|
||||||
done
|
done
|
Loading…
Reference in a new issue