mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-20 08:01:42 +03:00
Merge pull request #694 from AleoHQ/refactor/leo
Updates Leo CLI with safety enhancements, adds CircleCI resolving flaky tests
This commit is contained in:
commit
d85a057ddc
163
.circleci/config.yml
Normal file
163
.circleci/config.yml
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
version: 2.1
|
||||||
|
commands:
|
||||||
|
setup_environment:
|
||||||
|
description: "Setup environment"
|
||||||
|
parameters:
|
||||||
|
cache_key:
|
||||||
|
type: string
|
||||||
|
default: leo-stable-cache
|
||||||
|
steps:
|
||||||
|
- run: set -e
|
||||||
|
- setup_remote_docker
|
||||||
|
- run:
|
||||||
|
name: Prepare environment and install dependencies
|
||||||
|
command: |
|
||||||
|
export SCCACHE_CACHE_SIZE=200M
|
||||||
|
export WORK_DIR="$CIRCLE_WORKING_DIRECTORY/.cache/sccache"
|
||||||
|
export SCCACHE_DIR="$CIRCLE_WORKING_DIRECTORY/.cache/sccache"
|
||||||
|
mkdir -p "$CIRCLE_WORKING_DIRECTORY/.bin"
|
||||||
|
wget https://github.com/mozilla/sccache/releases/download/0.2.13/sccache-0.2.13-x86_64-unknown-linux-musl.tar.gz
|
||||||
|
tar -C "$CIRCLE_WORKING_DIRECTORY/.bin" -xvf sccache-0.2.13-x86_64-unknown-linux-musl.tar.gz
|
||||||
|
mv $CIRCLE_WORKING_DIRECTORY/.bin/sccache-0.2.13-x86_64-unknown-linux-musl/sccache $CIRCLE_WORKING_DIRECTORY/.bin/sccache
|
||||||
|
export PATH="$PATH:$CIRCLE_WORKING_DIRECTORY/.bin"
|
||||||
|
export RUSTC_WRAPPER="sccache"
|
||||||
|
rm -rf "$CIRCLE_WORKING_DIRECTORY/.cargo/registry"
|
||||||
|
sudo apt-get update && sudo apt-get install -y clang llvm-dev llvm pkg-config xz-utils make libssl-dev libssl-dev
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- << parameters.cache_key >>
|
||||||
|
clear_environment:
|
||||||
|
description: "Clear environment"
|
||||||
|
parameters:
|
||||||
|
cache_key:
|
||||||
|
type: string
|
||||||
|
default: leo-stable-cache
|
||||||
|
steps:
|
||||||
|
- run: (sccache -s||true)
|
||||||
|
- run: set +e
|
||||||
|
- save_cache:
|
||||||
|
key: << parameters.cache_key >>
|
||||||
|
paths:
|
||||||
|
- .cache/sccache
|
||||||
|
- .cargo
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
rust-stable:
|
||||||
|
docker:
|
||||||
|
- image: cimg/rust:1.50.0
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- setup_environment:
|
||||||
|
cache_key: leo-stable-cache
|
||||||
|
- run:
|
||||||
|
name: Build and run tests
|
||||||
|
no_output_timeout: 30m
|
||||||
|
command: cargo install --path . --root .
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: ~/
|
||||||
|
paths: project/
|
||||||
|
- clear_environment:
|
||||||
|
cache_key: leo-stable-cache
|
||||||
|
|
||||||
|
leo-new:
|
||||||
|
docker:
|
||||||
|
- image: cimg/rust:1.50.0
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: /home/circleci/project/
|
||||||
|
- run:
|
||||||
|
name: leo new
|
||||||
|
command: |
|
||||||
|
export LEO=/home/circleci/project/project/bin/leo
|
||||||
|
./project/.circleci/leo-new.sh
|
||||||
|
|
||||||
|
leo-init:
|
||||||
|
docker:
|
||||||
|
- image: cimg/rust:1.50.0
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: /home/circleci/project/
|
||||||
|
- run:
|
||||||
|
name: leo init
|
||||||
|
command: |
|
||||||
|
export LEO=/home/circleci/project/project/bin/leo
|
||||||
|
./project/.circleci/leo-init.sh
|
||||||
|
|
||||||
|
leo-clean:
|
||||||
|
docker:
|
||||||
|
- image: cimg/rust:1.50.0
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: /home/circleci/project/
|
||||||
|
- run:
|
||||||
|
name: leo clean
|
||||||
|
command: |
|
||||||
|
export LEO=/home/circleci/project/project/bin/leo
|
||||||
|
./project/.circleci/leo-clean.sh
|
||||||
|
|
||||||
|
leo-setup:
|
||||||
|
docker:
|
||||||
|
- image: cimg/rust:1.50.0
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: /home/circleci/project/
|
||||||
|
- run:
|
||||||
|
name: leo setup
|
||||||
|
command: |
|
||||||
|
export LEO=/home/circleci/project/project/bin/leo
|
||||||
|
./project/.circleci/leo-setup.sh
|
||||||
|
|
||||||
|
leo-add-remove:
|
||||||
|
docker:
|
||||||
|
- image: cimg/rust:1.50.0
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: /home/circleci/project/
|
||||||
|
- run:
|
||||||
|
name: leo add & remove
|
||||||
|
command: |
|
||||||
|
export LEO=/home/circleci/project/project/bin/leo
|
||||||
|
./project/.circleci/leo-add-remove.sh
|
||||||
|
|
||||||
|
leo-login-logout:
|
||||||
|
docker:
|
||||||
|
- image: cimg/rust:1.50.0
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: /home/circleci/project/
|
||||||
|
- run:
|
||||||
|
name: leo login & logout
|
||||||
|
command: |
|
||||||
|
export LEO=/home/circleci/project/project/bin/leo
|
||||||
|
./project/.circleci/leo-login-logout.sh
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
version: 2
|
||||||
|
main-workflow:
|
||||||
|
jobs:
|
||||||
|
- rust-stable
|
||||||
|
- leo-new:
|
||||||
|
requires:
|
||||||
|
- rust-stable
|
||||||
|
- leo-init:
|
||||||
|
requires:
|
||||||
|
- rust-stable
|
||||||
|
- leo-clean:
|
||||||
|
requires:
|
||||||
|
- rust-stable
|
||||||
|
- leo-setup:
|
||||||
|
requires:
|
||||||
|
- rust-stable
|
||||||
|
- leo-add-remove:
|
||||||
|
requires:
|
||||||
|
- rust-stable
|
||||||
|
- leo-login-logout:
|
||||||
|
requires:
|
||||||
|
- rust-stable
|
6
.circleci/leo-add-remove.sh
Executable file
6
.circleci/leo-add-remove.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
# leo add (w/o login) & remove
|
||||||
|
|
||||||
|
$LEO new my-app && cd my-app
|
||||||
|
$LEO add howard/silly-sudoku
|
||||||
|
$LEO remove silly-sudoku
|
||||||
|
$LEO clean
|
34
.circleci/leo-clean.sh
Executable file
34
.circleci/leo-clean.sh
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
# leo new hello-world
|
||||||
|
|
||||||
|
$LEO new hello-world
|
||||||
|
ls -la
|
||||||
|
cd hello-world && ls -la
|
||||||
|
$LEO run
|
||||||
|
|
||||||
|
# Assert that the 'outputs' folder is not empty
|
||||||
|
|
||||||
|
cd outputs || exit 1
|
||||||
|
if [ "$(ls -A $DIR)" ]; then
|
||||||
|
echo "$DIR is not empty"
|
||||||
|
else
|
||||||
|
echo "$DIR is empty"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# leo clean
|
||||||
|
|
||||||
|
$LEO clean
|
||||||
|
cd outputs && ls -la
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Assert that the 'outputs' folder is empty
|
||||||
|
|
||||||
|
cd outputs || exit 1
|
||||||
|
if [ "$(ls -A $DIR)" ]; then
|
||||||
|
echo "$DIR is not empty"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "$DIR is empty"
|
||||||
|
exit 0
|
||||||
|
fi
|
4
.circleci/leo-init.sh
Executable file
4
.circleci/leo-init.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
mkdir hello-world && cd hello-world || exit 1
|
||||||
|
$LEO init
|
||||||
|
ls -la
|
||||||
|
$LEO run
|
7
.circleci/leo-login-logout.sh
Executable file
7
.circleci/leo-login-logout.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
# leo login & logout
|
||||||
|
|
||||||
|
$LEO new my-app && cd my-app || exit 1
|
||||||
|
$LEO login -u "$ALEO_PM_USERNAME" -p "$ALEO_PM_PASSWORD"
|
||||||
|
$LEO add howard/silly-sudoku
|
||||||
|
$LEO remove silly-sudoku
|
||||||
|
$LEO logout
|
4
.circleci/leo-new.sh
Executable file
4
.circleci/leo-new.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
$LEO new hello-world
|
||||||
|
ls -la
|
||||||
|
cd hello-world && ls -la
|
||||||
|
$LEO run
|
7
.circleci/leo-setup.sh
Executable file
7
.circleci/leo-setup.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
# leo setup
|
||||||
|
|
||||||
|
cd ./project/examples/pedersen-hash || exit 1
|
||||||
|
$LEO setup
|
||||||
|
$LEO setup
|
||||||
|
$LEO setup --skip-key-check
|
||||||
|
$LEO clean
|
43
.github/workflows/leo-add-remove.yml
vendored
43
.github/workflows/leo-add-remove.yml
vendored
@ -1,43 +0,0 @@
|
|||||||
name: leo-add-remove
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'documentation/**'
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: 1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
add:
|
|
||||||
name: Add Package ('leo add')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Install Rust
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: nightly
|
|
||||||
override: true
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- name: Install Leo
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
env:
|
|
||||||
CARGO_NET_GIT_FETCH_WITH_CLI: true
|
|
||||||
with:
|
|
||||||
command: install
|
|
||||||
args: --path .
|
|
||||||
|
|
||||||
- name: 'leo add (w/o login) & remove'
|
|
||||||
run: |
|
|
||||||
cd .. && leo new my-app && cd my-app
|
|
||||||
leo add argus4130/xnor
|
|
||||||
leo remove xnor
|
|
||||||
leo clean
|
|
||||||
|
|
76
.github/workflows/leo-clean.yml
vendored
76
.github/workflows/leo-clean.yml
vendored
@ -1,76 +0,0 @@
|
|||||||
name: leo-clean
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'documentation/**'
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: 1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
new:
|
|
||||||
name: Hello Leo ('leo new hello-world')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Install Rust
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: nightly
|
|
||||||
override: true
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/registry
|
|
||||||
~/.cargo/git
|
|
||||||
target
|
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
|
||||||
|
|
||||||
- name: Install Leo
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: install
|
|
||||||
args: --path .
|
|
||||||
|
|
||||||
- name: 'leo new hello-world'
|
|
||||||
run: |
|
|
||||||
cd ..
|
|
||||||
leo new hello-world
|
|
||||||
ls -la
|
|
||||||
cd hello-world && ls -la
|
|
||||||
leo run
|
|
||||||
|
|
||||||
- name: Assert that the 'outputs' folder is not empty
|
|
||||||
run: |
|
|
||||||
cd ../hello-world/outputs
|
|
||||||
if [ "$(ls -A $DIR)" ]; then
|
|
||||||
echo "$DIR is not empty"
|
|
||||||
else
|
|
||||||
echo "$DIR is empty"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 'leo clean'
|
|
||||||
run: |
|
|
||||||
cd ../hello-world
|
|
||||||
leo clean
|
|
||||||
cd outputs && ls -la
|
|
||||||
|
|
||||||
- name: Assert that the 'outputs' folder is empty
|
|
||||||
run: |
|
|
||||||
cd ../hello-world/outputs
|
|
||||||
if [ "$(ls -A $DIR)" ]; then
|
|
||||||
echo "$DIR is not empty"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "$DIR is empty"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
48
.github/workflows/leo-init.yml
vendored
48
.github/workflows/leo-init.yml
vendored
@ -1,48 +0,0 @@
|
|||||||
name: leo-init
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'documentation/**'
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: 1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
init:
|
|
||||||
name: Hello Leo ('leo init')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Install Rust
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: nightly
|
|
||||||
override: true
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/registry
|
|
||||||
~/.cargo/git
|
|
||||||
target
|
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
|
||||||
|
|
||||||
- name: Install Leo
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: install
|
|
||||||
args: --path .
|
|
||||||
|
|
||||||
- name: 'leo init'
|
|
||||||
run: |
|
|
||||||
cd .. && mkdir hello-world && cd hello-world
|
|
||||||
leo init
|
|
||||||
ls -la
|
|
||||||
leo run
|
|
47
.github/workflows/leo-login-logout.yml
vendored
47
.github/workflows/leo-login-logout.yml
vendored
@ -1,47 +0,0 @@
|
|||||||
name: leo-login-logout
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'documentation/**'
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: 1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
add:
|
|
||||||
name: Add Package ('leo add')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Install Rust
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: nightly
|
|
||||||
override: true
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- name: Install Leo
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
env:
|
|
||||||
CARGO_NET_GIT_FETCH_WITH_CLI: true
|
|
||||||
with:
|
|
||||||
command: install
|
|
||||||
args: --path .
|
|
||||||
|
|
||||||
- name: 'leo login & logout'
|
|
||||||
env:
|
|
||||||
USER: ${{ secrets.ALEO_PM_USERNAME }}
|
|
||||||
PASS: ${{ secrets.ALEO_PM_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
cd .. && leo new my-app && cd my-app
|
|
||||||
leo login -u "$USER" -p "$PASS"
|
|
||||||
leo add argus4130/xnor
|
|
||||||
leo remove xnor
|
|
||||||
leo logout
|
|
||||||
|
|
49
.github/workflows/leo-new.yml
vendored
49
.github/workflows/leo-new.yml
vendored
@ -1,49 +0,0 @@
|
|||||||
name: leo-new
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'documentation/**'
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: 1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
new:
|
|
||||||
name: Hello Leo ('leo new hello-world')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Install Rust
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: nightly
|
|
||||||
override: true
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/registry
|
|
||||||
~/.cargo/git
|
|
||||||
target
|
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
|
||||||
|
|
||||||
- name: Install Leo
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: install
|
|
||||||
args: --path .
|
|
||||||
|
|
||||||
- name: 'leo new hello-world'
|
|
||||||
run: |
|
|
||||||
cd ..
|
|
||||||
leo new hello-world
|
|
||||||
ls -la
|
|
||||||
cd hello-world && ls -la
|
|
||||||
leo run
|
|
47
.github/workflows/leo-setup.yml
vendored
47
.github/workflows/leo-setup.yml
vendored
@ -1,47 +0,0 @@
|
|||||||
name: leo-setup
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'documentation/**'
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: 1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
add:
|
|
||||||
name: Add Package ('leo add')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Install Rust
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: nightly
|
|
||||||
override: true
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- name: Install Leo
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
env:
|
|
||||||
CARGO_NET_GIT_FETCH_WITH_CLI: true
|
|
||||||
with:
|
|
||||||
command: install
|
|
||||||
args: --path .
|
|
||||||
|
|
||||||
- name: 'leo setup for examples'
|
|
||||||
env:
|
|
||||||
USER: ${{ secrets.ALEO_PM_USERNAME }}
|
|
||||||
PASS: ${{ secrets.ALEO_PM_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
cd examples/pedersen-hash
|
|
||||||
leo setup
|
|
||||||
leo setup
|
|
||||||
leo setup --skip-key-check
|
|
||||||
leo clean
|
|
||||||
|
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -2,3 +2,9 @@
|
|||||||
/tmp/
|
/tmp/
|
||||||
**.idea/
|
**.idea/
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
|
||||||
|
**/process.yml
|
||||||
|
|
||||||
|
**/.crates.toml
|
||||||
|
**/.crates2.json
|
||||||
|
**/bin/
|
||||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
31
DEVELOPMENT.md
Normal file
31
DEVELOPMENT.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Development Guide
|
||||||
|
|
||||||
|
## Running CircleCI locally
|
||||||
|
|
||||||
|
### Step 1: Install CircleCI
|
||||||
|
|
||||||
|
If you wish to run CircleCI locally, start by installing it:
|
||||||
|
|
||||||
|
- macOS
|
||||||
|
```
|
||||||
|
brew install circleci
|
||||||
|
```
|
||||||
|
|
||||||
|
- Linux (via Snap)
|
||||||
|
```
|
||||||
|
sudo snap install docker circleci
|
||||||
|
sudo snap connect circleci:docker docker
|
||||||
|
```
|
||||||
|
|
||||||
|
- Windows (via Chocolatey)
|
||||||
|
```
|
||||||
|
choco install circleci-cli -y
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Run CircleCI
|
||||||
|
|
||||||
|
To run a job, export the config to `process.yml`, and specify it when executing:
|
||||||
|
```shell
|
||||||
|
circleci config process .circleci/config.yml > process.yml
|
||||||
|
circleci local execute -c process.yml --job JOB_NAME
|
||||||
|
```
|
@ -1,5 +1,5 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img width="1412" src="./.resources/leo.png">
|
<img width="1412" src=".resources/banner.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h1 align="center">The Leo Programming Language</h1>
|
<h1 align="center">The Leo Programming Language</h1>
|
||||||
@ -27,6 +27,7 @@ Leo is a functional, statically-typed programming language built for writing pri
|
|||||||
|
|
||||||
|
|
||||||
## 1. Overview
|
## 1. Overview
|
||||||
|
|
||||||
Welcome to the Leo programming language.
|
Welcome to the Leo programming language.
|
||||||
|
|
||||||
Leo provides a high-level language that abstracts low-level cryptographic concepts and makes it easy to
|
Leo provides a high-level language that abstracts low-level cryptographic concepts and makes it easy to
|
||||||
|
@ -40,7 +40,7 @@ fn load_asg_imports<'a, T: ImportResolver<'a>>(
|
|||||||
InternalProgram::new(context, &ast.as_repr(), imports)
|
InternalProgram::new(context, &ast.as_repr(), imports)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mocked_resolver<'a>(_ctx: AsgContext<'a>) -> MockedImportResolver<'a> {
|
fn mocked_resolver<'a>(_context: AsgContext<'a>) -> MockedImportResolver<'a> {
|
||||||
let packages = indexmap::IndexMap::new();
|
let packages = indexmap::IndexMap::new();
|
||||||
MockedImportResolver { packages }
|
MockedImportResolver { packages }
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ use std::path::Path;
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
let program_string = include_str!("./circuits/pedersen_mock.leo");
|
let program_string = include_str!("./circuits/pedersen_mock.leo");
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let asg = load_asg(&ctx, program_string).unwrap();
|
let asg = load_asg(&context, program_string).unwrap();
|
||||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||||
println!("{}", reformed_ast);
|
println!("{}", reformed_ast);
|
||||||
// panic!();
|
// panic!();
|
||||||
@ -51,8 +51,8 @@ fn test_function_rename() {
|
|||||||
console.assert(total == 20);
|
console.assert(total == 20);
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let asg = load_asg(&ctx, program_string).unwrap();
|
let asg = load_asg(&context, program_string).unwrap();
|
||||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||||
println!("{}", reformed_ast);
|
println!("{}", reformed_ast);
|
||||||
// panic!();
|
// panic!();
|
||||||
@ -60,8 +60,8 @@ fn test_function_rename() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_imports() {
|
fn test_imports() {
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let mut imports = crate::mocked_resolver(&ctx);
|
let mut imports = crate::mocked_resolver(&context);
|
||||||
let test_import = r#"
|
let test_import = r#"
|
||||||
circuit Point {
|
circuit Point {
|
||||||
x: u32
|
x: u32
|
||||||
@ -74,7 +74,7 @@ fn test_imports() {
|
|||||||
"#;
|
"#;
|
||||||
imports
|
imports
|
||||||
.packages
|
.packages
|
||||||
.insert("test-import".to_string(), load_asg(&ctx, test_import).unwrap());
|
.insert("test-import".to_string(), load_asg(&context, test_import).unwrap());
|
||||||
let program_string = r#"
|
let program_string = r#"
|
||||||
import test-import.foo;
|
import test-import.foo;
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ fn test_imports() {
|
|||||||
serde_json::to_string(Ast::new("test", &test_grammar).unwrap().as_repr()).unwrap()
|
serde_json::to_string(Ast::new("test", &test_grammar).unwrap().as_repr()).unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let asg = crate::load_asg_imports(&ctx, program_string, &mut imports).unwrap();
|
let asg = crate::load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||||
println!("{}", serde_json::to_string(&reformed_ast).unwrap());
|
println!("{}", serde_json::to_string(&reformed_ast).unwrap());
|
||||||
// panic!();
|
// panic!();
|
||||||
|
@ -20,138 +20,139 @@ use crate::{load_asg, load_asg_imports, mocked_resolver};
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let mut imports = mocked_resolver(&ctx);
|
let mut imports = mocked_resolver(&context);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"test-import".to_string(),
|
"test-import".to_string(),
|
||||||
load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
|
load_asg(&context, include_str!("src/test-import.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
let program_string = include_str!("basic.leo");
|
let program_string = include_str!("basic.leo");
|
||||||
load_asg_imports(&ctx, program_string, &mut imports).unwrap();
|
load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multiple() {
|
fn test_multiple() {
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let mut imports = mocked_resolver(&ctx);
|
let mut imports = mocked_resolver(&context);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"test-import".to_string(),
|
"test-import".to_string(),
|
||||||
load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
|
load_asg(&context, include_str!("src/test-import.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
let program_string = include_str!("multiple.leo");
|
let program_string = include_str!("multiple.leo");
|
||||||
load_asg_imports(&ctx, program_string, &mut imports).unwrap();
|
load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_star() {
|
fn test_star() {
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let mut imports = mocked_resolver(&ctx);
|
let mut imports = mocked_resolver(&context);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"test-import".to_string(),
|
"test-import".to_string(),
|
||||||
load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
|
load_asg(&context, include_str!("src/test-import.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let program_string = include_str!("star.leo");
|
let program_string = include_str!("star.leo");
|
||||||
load_asg_imports(&ctx, program_string, &mut imports).unwrap();
|
load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_alias() {
|
fn test_alias() {
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let mut imports = mocked_resolver(&ctx);
|
let mut imports = mocked_resolver(&context);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"test-import".to_string(),
|
"test-import".to_string(),
|
||||||
load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
|
load_asg(&context, include_str!("src/test-import.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let program_string = include_str!("alias.leo");
|
let program_string = include_str!("alias.leo");
|
||||||
load_asg_imports(&ctx, program_string, &mut imports).unwrap();
|
load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// naming tests
|
// naming tests
|
||||||
#[test]
|
#[test]
|
||||||
fn test_name() {
|
fn test_name() {
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let mut imports = mocked_resolver(&ctx);
|
let mut imports = mocked_resolver(&context);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"hello-world".to_string(),
|
"hello-world".to_string(),
|
||||||
load_asg(&ctx, include_str!("src/hello-world.leo")).unwrap(),
|
load_asg(&context, include_str!("src/hello-world.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"a0-f".to_string(),
|
"a0-f".to_string(),
|
||||||
load_asg(&ctx, include_str!("src/a0-f.leo")).unwrap(),
|
load_asg(&context, include_str!("src/a0-f.leo")).unwrap(),
|
||||||
|
);
|
||||||
|
imports.packages.insert(
|
||||||
|
"a-9".to_string(),
|
||||||
|
load_asg(&context, include_str!("src/a-9.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports
|
|
||||||
.packages
|
|
||||||
.insert("a-9".to_string(), load_asg(&ctx, include_str!("src/a-9.leo")).unwrap());
|
|
||||||
|
|
||||||
let program_string = include_str!("names.leo");
|
let program_string = include_str!("names.leo");
|
||||||
load_asg_imports(&ctx, program_string, &mut imports).unwrap();
|
load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// more complex tests
|
// more complex tests
|
||||||
#[test]
|
#[test]
|
||||||
fn test_many_import() {
|
fn test_many_import() {
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let mut imports = mocked_resolver(&ctx);
|
let mut imports = mocked_resolver(&context);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"test-import".to_string(),
|
"test-import".to_string(),
|
||||||
load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
|
load_asg(&context, include_str!("src/test-import.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"bar".to_string(),
|
"bar".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/bar/src/lib.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/bar/src/lib.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"bar.baz".to_string(),
|
"bar.baz".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/bar/src/baz.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/bar/src/baz.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"bar.baz".to_string(),
|
"bar.baz".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/bar/src/baz.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/bar/src/baz.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"bar.bat.bat".to_string(),
|
"bar.bat.bat".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/bar/src/bat/bat.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/bar/src/bat/bat.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"car".to_string(),
|
"car".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/car/src/lib.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/car/src/lib.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let program_string = include_str!("many_import.leo");
|
let program_string = include_str!("many_import.leo");
|
||||||
load_asg_imports(&ctx, program_string, &mut imports).unwrap();
|
load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_many_import_star() {
|
fn test_many_import_star() {
|
||||||
let ctx = new_context();
|
let context = new_context();
|
||||||
let mut imports = mocked_resolver(&ctx);
|
let mut imports = mocked_resolver(&context);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"test-import".to_string(),
|
"test-import".to_string(),
|
||||||
load_asg(&ctx, include_str!("src/test-import.leo")).unwrap(),
|
load_asg(&context, include_str!("src/test-import.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"bar".to_string(),
|
"bar".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/bar/src/lib.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/bar/src/lib.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"bar.baz".to_string(),
|
"bar.baz".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/bar/src/baz.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/bar/src/baz.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"bar.baz".to_string(),
|
"bar.baz".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/bar/src/baz.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/bar/src/baz.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"bar.bat.bat".to_string(),
|
"bar.bat.bat".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/bar/src/bat/bat.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/bar/src/bat/bat.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
imports.packages.insert(
|
imports.packages.insert(
|
||||||
"car".to_string(),
|
"car".to_string(),
|
||||||
load_asg(&ctx, include_str!("imports/car/src/lib.leo")).unwrap(),
|
load_asg(&context, include_str!("imports/car/src/lib.leo")).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let program_string = include_str!("many_import_star.leo");
|
let program_string = include_str!("many_import_star.leo");
|
||||||
load_asg_imports(&ctx, program_string, &mut imports).unwrap();
|
load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ pub struct Compiler<'a, F: PrimeField, G: GroupType<F>> {
|
|||||||
output_directory: PathBuf,
|
output_directory: PathBuf,
|
||||||
program: Program,
|
program: Program,
|
||||||
program_input: Input,
|
program_input: Input,
|
||||||
ctx: AsgContext<'a>,
|
context: AsgContext<'a>,
|
||||||
asg: Option<Asg<'a>>,
|
asg: Option<Asg<'a>>,
|
||||||
_engine: PhantomData<F>,
|
_engine: PhantomData<F>,
|
||||||
_group: PhantomData<G>,
|
_group: PhantomData<G>,
|
||||||
@ -73,7 +73,12 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
|||||||
///
|
///
|
||||||
/// Returns a new Leo program compiler.
|
/// Returns a new Leo program compiler.
|
||||||
///
|
///
|
||||||
pub fn new(package_name: String, main_file_path: PathBuf, output_directory: PathBuf, ctx: AsgContext<'a>) -> Self {
|
pub fn new(
|
||||||
|
package_name: String,
|
||||||
|
main_file_path: PathBuf,
|
||||||
|
output_directory: PathBuf,
|
||||||
|
context: AsgContext<'a>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
program_name: package_name.clone(),
|
program_name: package_name.clone(),
|
||||||
main_file_path,
|
main_file_path,
|
||||||
@ -81,7 +86,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
|||||||
program: Program::new(package_name),
|
program: Program::new(package_name),
|
||||||
program_input: Input::new(),
|
program_input: Input::new(),
|
||||||
asg: None,
|
asg: None,
|
||||||
ctx,
|
context,
|
||||||
_engine: PhantomData,
|
_engine: PhantomData,
|
||||||
_group: PhantomData,
|
_group: PhantomData,
|
||||||
}
|
}
|
||||||
@ -98,9 +103,9 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
|||||||
package_name: String,
|
package_name: String,
|
||||||
main_file_path: PathBuf,
|
main_file_path: PathBuf,
|
||||||
output_directory: PathBuf,
|
output_directory: PathBuf,
|
||||||
ctx: AsgContext<'a>,
|
context: AsgContext<'a>,
|
||||||
) -> Result<Self, CompilerError> {
|
) -> Result<Self, CompilerError> {
|
||||||
let mut compiler = Self::new(package_name, main_file_path, output_directory, ctx);
|
let mut compiler = Self::new(package_name, main_file_path, output_directory, context);
|
||||||
|
|
||||||
compiler.parse_program()?;
|
compiler.parse_program()?;
|
||||||
|
|
||||||
@ -124,9 +129,9 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
|||||||
input_path: &Path,
|
input_path: &Path,
|
||||||
state_string: &str,
|
state_string: &str,
|
||||||
state_path: &Path,
|
state_path: &Path,
|
||||||
ctx: AsgContext<'a>,
|
context: AsgContext<'a>,
|
||||||
) -> Result<Self, CompilerError> {
|
) -> Result<Self, CompilerError> {
|
||||||
let mut compiler = Self::new(package_name, main_file_path, output_directory, ctx);
|
let mut compiler = Self::new(package_name, main_file_path, output_directory, context);
|
||||||
|
|
||||||
compiler.parse_input(input_string, input_path, state_string, state_path)?;
|
compiler.parse_input(input_string, input_path, state_string, state_path)?;
|
||||||
|
|
||||||
@ -205,7 +210,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
|||||||
tracing::debug!("Program parsing complete\n{:#?}", self.program);
|
tracing::debug!("Program parsing complete\n{:#?}", self.program);
|
||||||
|
|
||||||
// Create a new symbol table from the program, imported_programs, and program_input.
|
// Create a new symbol table from the program, imported_programs, and program_input.
|
||||||
let asg = Asg::new(self.ctx, &core_ast, &mut leo_imports::ImportParser::default())?;
|
let asg = Asg::new(self.context, &core_ast, &mut leo_imports::ImportParser::default())?;
|
||||||
|
|
||||||
tracing::debug!("ASG generation complete");
|
tracing::debug!("ASG generation complete");
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ pub struct ImportParser<'a> {
|
|||||||
impl<'a> ImportResolver<'a> for ImportParser<'a> {
|
impl<'a> ImportResolver<'a> for ImportParser<'a> {
|
||||||
fn resolve_package(
|
fn resolve_package(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: AsgContext<'a>,
|
context: AsgContext<'a>,
|
||||||
package_segments: &[&str],
|
package_segments: &[&str],
|
||||||
span: &Span,
|
span: &Span,
|
||||||
) -> Result<Option<Program<'a>>, AsgConvertError> {
|
) -> Result<Option<Program<'a>>, AsgConvertError> {
|
||||||
@ -51,7 +51,7 @@ impl<'a> ImportResolver<'a> for ImportParser<'a> {
|
|||||||
|
|
||||||
self.partial_imports.insert(full_path.clone());
|
self.partial_imports.insert(full_path.clone());
|
||||||
let program = imports
|
let program = imports
|
||||||
.parse_package(ctx, path, package_segments, span)
|
.parse_package(context, path, package_segments, span)
|
||||||
.map_err(|x| -> AsgConvertError { x.into() })?;
|
.map_err(|x| -> AsgConvertError { x.into() })?;
|
||||||
self.partial_imports.remove(&full_path);
|
self.partial_imports.remove(&full_path);
|
||||||
self.imports.insert(full_path, program.clone());
|
self.imports.insert(full_path, program.clone());
|
||||||
|
@ -26,16 +26,16 @@ static IMPORTS_DIRECTORY_NAME: &str = "imports/";
|
|||||||
impl<'a> ImportParser<'a> {
|
impl<'a> ImportParser<'a> {
|
||||||
fn parse_package_access(
|
fn parse_package_access(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: AsgContext<'a>,
|
context: AsgContext<'a>,
|
||||||
package: &DirEntry,
|
package: &DirEntry,
|
||||||
remaining_segments: &[&str],
|
remaining_segments: &[&str],
|
||||||
span: &Span,
|
span: &Span,
|
||||||
) -> Result<Program<'a>, ImportParserError> {
|
) -> Result<Program<'a>, ImportParserError> {
|
||||||
if !remaining_segments.is_empty() {
|
if !remaining_segments.is_empty() {
|
||||||
return self.parse_package(ctx, package.path(), remaining_segments, span);
|
return self.parse_package(context, package.path(), remaining_segments, span);
|
||||||
}
|
}
|
||||||
let program = Self::parse_import_file(package, span)?;
|
let program = Self::parse_import_file(package, span)?;
|
||||||
let asg = leo_asg::InternalProgram::new(ctx, &program, self)?;
|
let asg = leo_asg::InternalProgram::new(context, &program, self)?;
|
||||||
|
|
||||||
Ok(asg)
|
Ok(asg)
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ impl<'a> ImportParser<'a> {
|
|||||||
///
|
///
|
||||||
pub(crate) fn parse_package(
|
pub(crate) fn parse_package(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: AsgContext<'a>,
|
context: AsgContext<'a>,
|
||||||
mut path: PathBuf,
|
mut path: PathBuf,
|
||||||
segments: &[&str],
|
segments: &[&str],
|
||||||
span: &Span,
|
span: &Span,
|
||||||
@ -113,8 +113,8 @@ impl<'a> ImportParser<'a> {
|
|||||||
package_name,
|
package_name,
|
||||||
span,
|
span,
|
||||||
))),
|
))),
|
||||||
(Some(source_entry), None) => self.parse_package_access(ctx, &source_entry, &segments[1..], span),
|
(Some(source_entry), None) => self.parse_package_access(context, &source_entry, &segments[1..], span),
|
||||||
(None, Some(import_entry)) => self.parse_package_access(ctx, &import_entry, &segments[1..], span),
|
(None, Some(import_entry)) => self.parse_package_access(context, &import_entry, &segments[1..], span),
|
||||||
(None, None) => Err(ImportParserError::unknown_package(Identifier::new_with_span(
|
(None, None) => Err(ImportParserError::unknown_package(Identifier::new_with_span(
|
||||||
package_name,
|
package_name,
|
||||||
span,
|
span,
|
||||||
@ -123,7 +123,7 @@ impl<'a> ImportParser<'a> {
|
|||||||
} else {
|
} else {
|
||||||
// Enforce local package access with no found imports directory
|
// Enforce local package access with no found imports directory
|
||||||
match matched_source_entry {
|
match matched_source_entry {
|
||||||
Some(source_entry) => self.parse_package_access(ctx, &source_entry, &segments[1..], span),
|
Some(source_entry) => self.parse_package_access(context, &source_entry, &segments[1..], span),
|
||||||
None => Err(ImportParserError::unknown_package(Identifier::new_with_span(
|
None => Err(ImportParserError::unknown_package(Identifier::new_with_span(
|
||||||
package_name,
|
package_name,
|
||||||
span,
|
span,
|
||||||
|
@ -36,16 +36,10 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Compile and build program command
|
/// Compile and build program command
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Build {}
|
pub struct Build {}
|
||||||
|
|
||||||
impl Build {
|
|
||||||
pub fn new() -> Build {
|
|
||||||
Build {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for Build {
|
impl Command for Build {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = Option<(Compiler<'static, Fq, EdwardsGroupType>, bool)>;
|
type Output = Option<(Compiler<'static, Fq, EdwardsGroupType>, bool)>;
|
||||||
@ -58,9 +52,9 @@ impl Command for Build {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, ctx: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
let path = ctx.dir()?;
|
let path = context.dir()?;
|
||||||
let package_name = ctx.manifest()?.get_package_name();
|
let package_name = context.manifest()?.get_package_name();
|
||||||
|
|
||||||
// Sanitize the package path to the root directory
|
// Sanitize the package path to the root directory
|
||||||
let mut package_path = path.clone();
|
let mut package_path = path.clone();
|
||||||
@ -140,8 +134,8 @@ impl Command for Build {
|
|||||||
let temporary_program = program.clone();
|
let temporary_program = program.clone();
|
||||||
let output = temporary_program.compile_constraints(&mut cs)?;
|
let output = temporary_program.compile_constraints(&mut cs)?;
|
||||||
|
|
||||||
tracing::debug!("Compiled constraints - {:#?}", output);
|
tracing::debug!("Compiled output - {:#?}", output);
|
||||||
tracing::debug!("Number of constraints - {:#?}", cs.num_constraints());
|
tracing::info!("Number of constraints - {:#?}", cs.num_constraints());
|
||||||
|
|
||||||
// Serialize the circuit
|
// Serialize the circuit
|
||||||
let circuit_object = SerializedCircuit::from(cs);
|
let circuit_object = SerializedCircuit::from(cs);
|
||||||
|
@ -23,16 +23,10 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Clean outputs folder command
|
/// Clean outputs folder command
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Clean {}
|
pub struct Clean {}
|
||||||
|
|
||||||
impl Clean {
|
|
||||||
pub fn new() -> Clean {
|
|
||||||
Clean {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for Clean {
|
impl Command for Clean {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = ();
|
type Output = ();
|
||||||
@ -45,9 +39,9 @@ impl Command for Clean {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, ctx: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
let path = ctx.dir()?;
|
let path = context.dir()?;
|
||||||
let package_name = ctx.manifest()?.get_package_name();
|
let package_name = context.manifest()?.get_package_name();
|
||||||
|
|
||||||
// Remove the checksum from the output directory
|
// Remove the checksum from the output directory
|
||||||
ChecksumFile::new(&package_name).remove(&path)?;
|
ChecksumFile::new(&package_name).remove(&path)?;
|
||||||
|
@ -21,16 +21,10 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Deploy Leo program to the network
|
/// Deploy Leo program to the network
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Deploy {}
|
pub struct Deploy {}
|
||||||
|
|
||||||
impl Deploy {
|
|
||||||
pub fn new() -> Deploy {
|
|
||||||
Deploy {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for Deploy {
|
impl Command for Deploy {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
@ -23,16 +23,10 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Init Leo project command within current directory
|
/// Init Leo project command within current directory
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Init {}
|
pub struct Init {}
|
||||||
|
|
||||||
impl Init {
|
|
||||||
pub fn new() -> Init {
|
|
||||||
Init {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for Init {
|
impl Command for Init {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = ();
|
type Output = ();
|
||||||
@ -46,13 +40,20 @@ impl Command for Init {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, _: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, _: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
|
// Derive the package directory path.
|
||||||
let path = current_dir()?;
|
let path = current_dir()?;
|
||||||
|
|
||||||
|
// Check that the given package name is valid.
|
||||||
let package_name = path
|
let package_name = path
|
||||||
.file_stem()
|
.file_stem()
|
||||||
.ok_or_else(|| anyhow!("Project name invalid"))?
|
.ok_or_else(|| anyhow!("Project name invalid"))?
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string();
|
.to_string();
|
||||||
|
if !LeoPackage::is_package_name_valid(&package_name) {
|
||||||
|
return Err(anyhow!("Invalid Leo project name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the current package directory path exists.
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
return Err(anyhow!("Directory does not exist"));
|
return Err(anyhow!("Directory does not exist"));
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,10 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Lint Leo code command
|
/// Lint Leo code command
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Lint {}
|
pub struct Lint {}
|
||||||
|
|
||||||
impl Lint {
|
|
||||||
pub fn new() -> Lint {
|
|
||||||
Lint {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for Lint {
|
impl Command for Lint {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
@ -52,7 +52,7 @@ pub mod test;
|
|||||||
pub use test::Test;
|
pub use test::Test;
|
||||||
|
|
||||||
pub mod update;
|
pub mod update;
|
||||||
pub use update::{Sub as UpdateAutomatic, Update};
|
pub use update::{Automatic as UpdateAutomatic, Update};
|
||||||
|
|
||||||
pub mod watch;
|
pub mod watch;
|
||||||
pub use watch::Watch;
|
pub use watch::Watch;
|
||||||
@ -60,57 +60,55 @@ pub use watch::Watch;
|
|||||||
// Aleo PM related commands
|
// Aleo PM related commands
|
||||||
pub mod package;
|
pub mod package;
|
||||||
|
|
||||||
/// Base trait for Leo CLI, see methods and their documentation for details
|
/// Base trait for the Leo CLI, see methods and their documentation for details.
|
||||||
pub trait Command {
|
pub trait Command {
|
||||||
/// If current command requires running another command before
|
/// If the current command requires running another command beforehand
|
||||||
/// and needs its output results, this is the place to set.
|
/// and needs its output result, this is where the result type is defined.
|
||||||
/// Example: type Input: <CommandA as Command>::Out
|
/// Example: type Input: <CommandA as Command>::Out
|
||||||
type Input;
|
type Input;
|
||||||
|
|
||||||
/// Define output of the command to be reused as an Input for another
|
/// Defines the output of this command, which may be used as `Input` for another
|
||||||
/// command. If this command is not used as a prelude for another, keep empty
|
/// command. If this command is not used as a prelude for another command,
|
||||||
|
/// this field may be left empty.
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Returns project context, currently keeping it simple but it is possible
|
/// Returns the project context, which is defined as the current directory.
|
||||||
/// that in the future leo will not depend on current directory, and we're keeping
|
|
||||||
/// option for extending current core
|
|
||||||
fn context(&self) -> Result<Context> {
|
fn context(&self) -> Result<Context> {
|
||||||
get_context()
|
get_context()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add span to the logger tracing::span.
|
/// Adds a span to the logger via `tracing::span`.
|
||||||
/// Due to specifics of macro implementation it is impossible to set
|
/// Because of the specifics of the macro implementation, it is not possible
|
||||||
/// span name with non-literal i.e. dynamic variable even if this
|
/// to set the span name with a non-literal i.e. a dynamic variable even if this
|
||||||
/// variable is &'static str
|
/// variable is a &'static str.
|
||||||
fn log_span(&self) -> Span {
|
fn log_span(&self) -> Span {
|
||||||
tracing::span!(tracing::Level::INFO, "Leo")
|
tracing::span!(tracing::Level::INFO, "Leo")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run prelude and get Input for current command. As simple as that.
|
/// Runs the prelude and returns the Input of the current command.
|
||||||
/// But due to inability to pass default implementation of a type, this
|
|
||||||
/// method must be present in every trait implementation.
|
|
||||||
fn prelude(&self) -> Result<Self::Input>
|
fn prelude(&self) -> Result<Self::Input>
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized;
|
Self: std::marker::Sized;
|
||||||
|
|
||||||
/// Core of the execution - do what is necessary. This function is run within
|
/// Runs the main operation of this command. This function is run within
|
||||||
/// context of 'execute' function, which sets logging and timers
|
/// context of 'execute' function, which sets logging and timers.
|
||||||
fn apply(self, ctx: Context, input: Self::Input) -> Result<Self::Output>
|
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output>
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized;
|
Self: std::marker::Sized;
|
||||||
|
|
||||||
/// Wrapper around apply function, sets up tracing, time tracking and context
|
/// A wrapper around the `apply` method.
|
||||||
|
/// This function sets up tracing, timing, and the context.
|
||||||
fn execute(self) -> Result<Self::Output>
|
fn execute(self) -> Result<Self::Output>
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized,
|
Self: std::marker::Sized,
|
||||||
{
|
{
|
||||||
let input = self.prelude()?;
|
let input = self.prelude()?;
|
||||||
|
|
||||||
// create span for this command
|
// Create the span for this command.
|
||||||
let span = self.log_span();
|
let span = self.log_span();
|
||||||
let span = span.enter();
|
let span = span.enter();
|
||||||
|
|
||||||
// calculate execution time for each run
|
// Calculate the execution time for this command.
|
||||||
let timer = Instant::now();
|
let timer = Instant::now();
|
||||||
|
|
||||||
let context = self.context()?;
|
let context = self.context()?;
|
||||||
@ -118,7 +116,7 @@ pub trait Command {
|
|||||||
|
|
||||||
drop(span);
|
drop(span);
|
||||||
|
|
||||||
// use done context to print time
|
// Use the done context to print the execution time for this command.
|
||||||
tracing::span!(tracing::Level::INFO, "Done").in_scope(|| {
|
tracing::span!(tracing::Level::INFO, "Done").in_scope(|| {
|
||||||
tracing::info!("Finished in {} milliseconds \n", timer.elapsed().as_millis());
|
tracing::info!("Finished in {} milliseconds \n", timer.elapsed().as_millis());
|
||||||
});
|
});
|
||||||
@ -126,7 +124,7 @@ pub trait Command {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute command but empty the result. Comes in handy where there's a
|
/// Executes command but empty the result. Comes in handy where there's a
|
||||||
/// need to make match arms compatible while keeping implementation-specific
|
/// need to make match arms compatible while keeping implementation-specific
|
||||||
/// output possible. Errors however are all of the type Error
|
/// output possible. Errors however are all of the type Error
|
||||||
fn try_execute(self) -> Result<()>
|
fn try_execute(self) -> Result<()>
|
||||||
|
@ -30,12 +30,6 @@ pub struct New {
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl New {
|
|
||||||
pub fn new(name: String) -> New {
|
|
||||||
New { name }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for New {
|
impl Command for New {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = ();
|
type Output = ();
|
||||||
@ -49,13 +43,17 @@ impl Command for New {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, _: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, _: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
let mut path = current_dir()?;
|
// Check that the given package name is valid.
|
||||||
let package_name = self.name;
|
let package_name = self.name;
|
||||||
|
if !LeoPackage::is_package_name_valid(&package_name) {
|
||||||
|
return Err(anyhow!("Invalid Leo project name"));
|
||||||
|
}
|
||||||
|
|
||||||
// Derive the package directory path
|
// Derive the package directory path.
|
||||||
|
let mut path = current_dir()?;
|
||||||
path.push(&package_name);
|
path.push(&package_name);
|
||||||
|
|
||||||
// Verify the package directory path does not exist yet
|
// Verify the package directory path does not exist yet.
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
return Err(anyhow!("Directory already exists {:?}", path));
|
return Err(anyhow!("Directory already exists {:?}", path));
|
||||||
}
|
}
|
||||||
|
@ -90,9 +90,9 @@ impl Command for Add {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, ctx: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
// checking that manifest exists...
|
// checking that manifest exists...
|
||||||
if ctx.manifest().is_err() {
|
if context.manifest().is_err() {
|
||||||
return Err(anyhow!("Package Manifest not found, try running leo init or leo new"));
|
return Err(anyhow!("Package Manifest not found, try running leo init or leo new"));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -109,8 +109,8 @@ impl Command for Add {
|
|||||||
version,
|
version,
|
||||||
};
|
};
|
||||||
|
|
||||||
let bytes = ctx.api.run_route(fetch)?.bytes()?;
|
let bytes = context.api.run_route(fetch)?.bytes()?;
|
||||||
let mut path = ctx.dir()?;
|
let mut path = context.dir()?;
|
||||||
|
|
||||||
{
|
{
|
||||||
// setup directory structure since request was success
|
// setup directory structure since request was success
|
||||||
|
@ -58,14 +58,14 @@ impl Command for Login {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, ctx: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
// quick hack to check if user is already logged in. ;)
|
// quick hack to check if user is already logged in. ;)
|
||||||
if ctx.api.auth_token().is_some() {
|
if context.api.auth_token().is_some() {
|
||||||
tracing::info!("You are already logged in");
|
tracing::info!("You are already logged in");
|
||||||
return Ok(ctx.api.auth_token().unwrap());
|
return Ok(context.api.auth_token().unwrap());
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut api = ctx.api;
|
let mut api = context.api;
|
||||||
|
|
||||||
// ...or trying to use arguments to either get token or user-pass
|
// ...or trying to use arguments to either get token or user-pass
|
||||||
let token = match (self.token, self.user, self.pass) {
|
let token = match (self.token, self.user, self.pass) {
|
||||||
|
@ -22,16 +22,10 @@ use structopt::StructOpt;
|
|||||||
use tracing::Span;
|
use tracing::Span;
|
||||||
|
|
||||||
/// Remove credentials for Aleo PM from .leo directory
|
/// Remove credentials for Aleo PM from .leo directory
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Logout {}
|
pub struct Logout {}
|
||||||
|
|
||||||
impl Logout {
|
|
||||||
pub fn new() -> Logout {
|
|
||||||
Logout {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for Logout {
|
impl Command for Logout {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = ();
|
type Output = ();
|
||||||
@ -44,7 +38,7 @@ impl Command for Logout {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, _ctx: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
// the only error we're interested here is NotFound
|
// the only error we're interested here is NotFound
|
||||||
// however err in this case can also be of kind PermissionDenied or other
|
// however err in this case can also be of kind PermissionDenied or other
|
||||||
if let Err(err) = remove_token() {
|
if let Err(err) = remove_token() {
|
||||||
|
@ -37,29 +37,23 @@ struct ResponseJson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Publish package to Aleo Package Manager
|
/// Publish package to Aleo Package Manager
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Publish {}
|
pub struct Publish {}
|
||||||
|
|
||||||
impl Publish {
|
|
||||||
pub fn new() -> Publish {
|
|
||||||
Publish {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for Publish {
|
impl Command for Publish {
|
||||||
type Input = <Build as Command>::Output;
|
type Input = <Build as Command>::Output;
|
||||||
type Output = Option<String>;
|
type Output = Option<String>;
|
||||||
|
|
||||||
/// Build program before publishing
|
/// Build program before publishing
|
||||||
fn prelude(&self) -> Result<Self::Input> {
|
fn prelude(&self) -> Result<Self::Input> {
|
||||||
Build::new().execute()
|
(Build {}).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, ctx: Context, _input: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, _input: Self::Input) -> Result<Self::Output> {
|
||||||
// Get the package manifest
|
// Get the package manifest
|
||||||
let path = ctx.dir()?;
|
let path = context.dir()?;
|
||||||
let manifest = ctx.manifest()?;
|
let manifest = context.manifest()?;
|
||||||
|
|
||||||
let package_name = manifest.get_package_name();
|
let package_name = manifest.get_package_name();
|
||||||
let package_version = manifest.get_package_version();
|
let package_version = manifest.get_package_version();
|
||||||
@ -99,7 +93,7 @@ impl Command for Publish {
|
|||||||
// Client for make POST request
|
// Client for make POST request
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
|
|
||||||
let token = match ctx.api.auth_token() {
|
let token = match context.api.auth_token() {
|
||||||
Some(token) => token,
|
Some(token) => token,
|
||||||
None => return Err(anyhow!("Login before publishing package: try leo login --help")),
|
None => return Err(anyhow!("Login before publishing package: try leo login --help")),
|
||||||
};
|
};
|
||||||
|
@ -22,19 +22,13 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Remove imported package
|
/// Remove imported package
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Remove {
|
pub struct Remove {
|
||||||
#[structopt(name = "PACKAGE")]
|
#[structopt(name = "PACKAGE")]
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Remove {
|
|
||||||
pub fn new(name: String) -> Remove {
|
|
||||||
Remove { name }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for Remove {
|
impl Command for Remove {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = ();
|
type Output = ();
|
||||||
@ -47,8 +41,8 @@ impl Command for Remove {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, ctx: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
let path = ctx.dir()?;
|
let path = context.dir()?;
|
||||||
let package_name = self.name;
|
let package_name = self.name;
|
||||||
|
|
||||||
LeoPackage::remove_imported_package(&package_name, &path)?;
|
LeoPackage::remove_imported_package(&package_name, &path)?;
|
||||||
|
@ -28,17 +28,11 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Run the program and produce a proof
|
/// Run the program and produce a proof
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Prove {
|
pub struct Prove {
|
||||||
#[structopt(long = "skip-key-check", help = "Skip key verification on Setup stage")]
|
#[structopt(long = "skip-key-check", help = "Skip key verification on Setup stage")]
|
||||||
skip_key_check: bool,
|
pub(crate) skip_key_check: bool,
|
||||||
}
|
|
||||||
|
|
||||||
impl Prove {
|
|
||||||
pub fn new(skip_key_check: bool) -> Prove {
|
|
||||||
Prove { skip_key_check }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for Prove {
|
impl Command for Prove {
|
||||||
@ -50,15 +44,16 @@ impl Command for Prove {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prelude(&self) -> Result<Self::Input> {
|
fn prelude(&self) -> Result<Self::Input> {
|
||||||
Setup::new(self.skip_key_check).execute()
|
let skip_key_check = self.skip_key_check;
|
||||||
|
(Setup { skip_key_check }).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, ctx: Context, input: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {
|
||||||
let (program, parameters, prepared_verifying_key) = input;
|
let (program, parameters, prepared_verifying_key) = input;
|
||||||
|
|
||||||
// Get the package name
|
// Get the package name
|
||||||
let path = ctx.dir()?;
|
let path = context.dir()?;
|
||||||
let package_name = ctx.manifest()?.get_package_name();
|
let package_name = context.manifest()?.get_package_name();
|
||||||
|
|
||||||
tracing::info!("Starting...");
|
tracing::info!("Starting...");
|
||||||
|
|
||||||
|
@ -26,17 +26,11 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Build, Prove and Run Leo program with inputs
|
/// Build, Prove and Run Leo program with inputs
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Run {
|
pub struct Run {
|
||||||
#[structopt(long = "skip-key-check", help = "Skip key verification on Setup stage")]
|
#[structopt(long = "skip-key-check", help = "Skip key verification on Setup stage")]
|
||||||
skip_key_check: bool,
|
pub(crate) skip_key_check: bool,
|
||||||
}
|
|
||||||
|
|
||||||
impl Run {
|
|
||||||
pub fn new(skip_key_check: bool) -> Run {
|
|
||||||
Run { skip_key_check }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for Run {
|
impl Command for Run {
|
||||||
@ -48,10 +42,11 @@ impl Command for Run {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prelude(&self) -> Result<Self::Input> {
|
fn prelude(&self) -> Result<Self::Input> {
|
||||||
Prove::new(self.skip_key_check).execute()
|
let skip_key_check = self.skip_key_check;
|
||||||
|
(Prove { skip_key_check }).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, _ctx: Context, input: Self::Input) -> Result<Self::Output> {
|
fn apply(self, _context: Context, input: Self::Input) -> Result<Self::Output> {
|
||||||
let (proof, prepared_verifying_key) = input;
|
let (proof, prepared_verifying_key) = input;
|
||||||
|
|
||||||
tracing::info!("Starting...");
|
tracing::info!("Starting...");
|
||||||
|
@ -31,17 +31,11 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Executes the setup command for a Leo program
|
/// Executes the setup command for a Leo program
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Setup {
|
pub struct Setup {
|
||||||
#[structopt(long = "skip-key-check", help = "Skip key verification")]
|
#[structopt(long = "skip-key-check", help = "Skip key verification")]
|
||||||
skip_key_check: bool,
|
pub(crate) skip_key_check: bool,
|
||||||
}
|
|
||||||
|
|
||||||
impl Setup {
|
|
||||||
pub fn new(skip_key_check: bool) -> Setup {
|
|
||||||
Setup { skip_key_check }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for Setup {
|
impl Command for Setup {
|
||||||
@ -57,12 +51,12 @@ impl Command for Setup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prelude(&self) -> Result<Self::Input> {
|
fn prelude(&self) -> Result<Self::Input> {
|
||||||
Build::new().execute()
|
(Build {}).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, ctx: Context, input: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {
|
||||||
let path = ctx.dir()?;
|
let path = context.dir()?;
|
||||||
let package_name = ctx.manifest()?.get_package_name();
|
let package_name = context.manifest()?.get_package_name();
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
Some((program, checksum_differs)) => {
|
Some((program, checksum_differs)) => {
|
||||||
@ -70,7 +64,6 @@ impl Command for Setup {
|
|||||||
let keys_exist = ProvingKeyFile::new(&package_name).exists_at(&path)
|
let keys_exist = ProvingKeyFile::new(&package_name).exists_at(&path)
|
||||||
&& VerificationKeyFile::new(&package_name).exists_at(&path);
|
&& VerificationKeyFile::new(&package_name).exists_at(&path);
|
||||||
|
|
||||||
// If keys do not exist or the checksum differs, run the program setup
|
|
||||||
// If keys do not exist or the checksum differs, run the program setup
|
// If keys do not exist or the checksum differs, run the program setup
|
||||||
let (proving_key, prepared_verifying_key) = if !keys_exist || checksum_differs {
|
let (proving_key, prepared_verifying_key) = if !keys_exist || checksum_differs {
|
||||||
tracing::info!("Starting...");
|
tracing::info!("Starting...");
|
||||||
|
@ -32,17 +32,11 @@ use structopt::StructOpt;
|
|||||||
use tracing::span::Span;
|
use tracing::span::Span;
|
||||||
|
|
||||||
/// Build program and run tests command
|
/// Build program and run tests command
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Test {
|
pub struct Test {
|
||||||
#[structopt(short = "f", long = "file", name = "file")]
|
#[structopt(short = "f", long = "file", name = "file")]
|
||||||
files: Vec<PathBuf>,
|
pub(crate) files: Vec<PathBuf>,
|
||||||
}
|
|
||||||
|
|
||||||
impl Test {
|
|
||||||
pub fn new(files: Vec<PathBuf>) -> Test {
|
|
||||||
Test { files }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for Test {
|
impl Command for Test {
|
||||||
@ -57,12 +51,12 @@ impl Command for Test {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, ctx: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
// Get the package name
|
// Get the package name
|
||||||
let package_name = ctx.manifest()?.get_package_name();
|
let package_name = context.manifest()?.get_package_name();
|
||||||
|
|
||||||
// Sanitize the package path to the root directory
|
// Sanitize the package path to the root directory
|
||||||
let mut package_path = ctx.dir()?;
|
let mut package_path = context.dir()?;
|
||||||
if package_path.is_file() {
|
if package_path.is_file() {
|
||||||
package_path.pop();
|
package_path.pop();
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ use tracing::span::Span;
|
|||||||
|
|
||||||
/// Setting for automatic updates of Leo
|
/// Setting for automatic updates of Leo
|
||||||
#[derive(Debug, StructOpt, PartialEq)]
|
#[derive(Debug, StructOpt, PartialEq)]
|
||||||
pub enum Sub {
|
pub enum Automatic {
|
||||||
Automatic {
|
Automatic {
|
||||||
#[structopt(name = "bool", help = "Boolean value: true or false", parse(try_from_str))]
|
#[structopt(name = "bool", help = "Boolean value: true or false", parse(try_from_str))]
|
||||||
value: bool,
|
value: bool,
|
||||||
@ -30,30 +30,20 @@ pub enum Sub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update Leo to the latest version
|
/// Update Leo to the latest version
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Update {
|
pub struct Update {
|
||||||
/// List all available versions of Leo
|
/// List all available versions of Leo
|
||||||
#[structopt(short, long)]
|
#[structopt(short, long)]
|
||||||
list: bool,
|
pub(crate) list: bool,
|
||||||
|
|
||||||
/// For Aleo Studio only
|
/// For Aleo Studio only
|
||||||
#[structopt(short, long)]
|
#[structopt(short, long)]
|
||||||
studio: bool,
|
pub(crate) studio: bool,
|
||||||
|
|
||||||
/// Setting for automatic updates of Leo
|
/// Setting for automatic updates of Leo
|
||||||
#[structopt(subcommand)]
|
#[structopt(subcommand)]
|
||||||
automatic: Option<Sub>,
|
pub(crate) automatic: Option<Automatic>,
|
||||||
}
|
|
||||||
|
|
||||||
impl Update {
|
|
||||||
pub fn new(list: bool, studio: bool, automatic: Option<Sub>) -> Update {
|
|
||||||
Update {
|
|
||||||
list,
|
|
||||||
studio,
|
|
||||||
automatic,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for Update {
|
impl Command for Update {
|
||||||
@ -69,13 +59,13 @@ impl Command for Update {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, _: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, _: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
// if --list is passed - simply list everything and exit
|
// If --list is passed, list all available versions and return.
|
||||||
if self.list {
|
if self.list {
|
||||||
return Updater::show_available_releases().map_err(|e| anyhow!("Could not fetch versions: {}", e));
|
return Updater::show_available_releases().map_err(|e| anyhow!("Could not fetch versions: {}", e));
|
||||||
}
|
}
|
||||||
|
|
||||||
// in case automatic subcommand was called
|
// Handles enabling and disabling automatic updates in the config file.
|
||||||
if let Some(Sub::Automatic { value }) = self.automatic {
|
if let Some(Automatic::Automatic { value }) = self.automatic {
|
||||||
Config::set_update_automatic(value)?;
|
Config::set_update_automatic(value)?;
|
||||||
|
|
||||||
match value {
|
match value {
|
||||||
|
@ -27,7 +27,7 @@ use tracing::span::Span;
|
|||||||
const LEO_SOURCE_DIR: &str = "src/";
|
const LEO_SOURCE_DIR: &str = "src/";
|
||||||
|
|
||||||
/// Watch file changes in src/ directory and run Build Command
|
/// Watch file changes in src/ directory and run Build Command
|
||||||
#[derive(StructOpt, Debug, Default)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||||
pub struct Watch {
|
pub struct Watch {
|
||||||
/// Set up watch interval
|
/// Set up watch interval
|
||||||
@ -35,12 +35,6 @@ pub struct Watch {
|
|||||||
interval: u64,
|
interval: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Watch {
|
|
||||||
pub fn new(interval: u64) -> Watch {
|
|
||||||
Watch { interval }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command for Watch {
|
impl Command for Watch {
|
||||||
type Input = ();
|
type Input = ();
|
||||||
type Output = ();
|
type Output = ();
|
||||||
@ -53,7 +47,7 @@ impl Command for Watch {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply(self, _ctx: Context, _: Self::Input) -> Result<Self::Output> {
|
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let mut watcher = watcher(tx, Duration::from_secs(self.interval)).unwrap();
|
let mut watcher = watcher(tx, Duration::from_secs(self.interval)).unwrap();
|
||||||
|
|
||||||
@ -70,7 +64,7 @@ impl Command for Watch {
|
|||||||
match rx.recv() {
|
match rx.recv() {
|
||||||
// See changes on the write event
|
// See changes on the write event
|
||||||
Ok(DebouncedEvent::Write(_write)) => {
|
Ok(DebouncedEvent::Write(_write)) => {
|
||||||
match Build::new().execute() {
|
match (Build {}).execute() {
|
||||||
Ok(_output) => {
|
Ok(_output) => {
|
||||||
tracing::info!("Built successfully");
|
tracing::info!("Built successfully");
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,12 @@ where
|
|||||||
N: for<'a> FormatFields<'a> + 'static,
|
N: for<'a> FormatFields<'a> + 'static,
|
||||||
T: FormatTime,
|
T: FormatTime,
|
||||||
{
|
{
|
||||||
fn format_event(&self, ctx: &FmtContext<'_, S, N>, writer: &mut dyn fmt::Write, event: &Event<'_>) -> fmt::Result {
|
fn format_event(
|
||||||
|
&self,
|
||||||
|
context: &FmtContext<'_, S, N>,
|
||||||
|
writer: &mut dyn fmt::Write,
|
||||||
|
event: &Event<'_>,
|
||||||
|
) -> fmt::Result {
|
||||||
let meta = event.metadata();
|
let meta = event.metadata();
|
||||||
|
|
||||||
if self.display_level {
|
if self.display_level {
|
||||||
@ -174,7 +179,7 @@ where
|
|||||||
|
|
||||||
let mut message = "".to_string();
|
let mut message = "".to_string();
|
||||||
|
|
||||||
let scope = ctx.scope();
|
let scope = context.scope();
|
||||||
for span in scope {
|
for span in scope {
|
||||||
message += span.metadata().name();
|
message += span.metadata().name();
|
||||||
|
|
||||||
@ -190,7 +195,7 @@ where
|
|||||||
write!(writer, "{:>10} ", colored_string(meta.level(), &message)).expect("Error writing event");
|
write!(writer, "{:>10} ", colored_string(meta.level(), &message)).expect("Error writing event");
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.format_fields(writer, event)?;
|
context.format_fields(writer, event)?;
|
||||||
writeln!(writer)
|
writeln!(writer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,34 +39,34 @@ const PEDERSEN_HASH_PATH: &str = "./examples/pedersen-hash/";
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn build_pedersen_hash() -> Result<()> {
|
pub fn build_pedersen_hash() -> Result<()> {
|
||||||
Build::new().apply(ctx()?, ())?;
|
(Build {}).apply(context()?, ())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn setup_pedersen_hash() -> Result<()> {
|
pub fn setup_pedersen_hash() -> Result<()> {
|
||||||
let build = Build::new().apply(ctx()?, ())?;
|
let build = (Build {}).apply(context()?, ())?;
|
||||||
Setup::new(false).apply(ctx()?, build.clone())?;
|
(Setup { skip_key_check: false }).apply(context()?, build.clone())?;
|
||||||
Setup::new(true).apply(ctx()?, build)?;
|
(Setup { skip_key_check: true }).apply(context()?, build)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn prove_pedersen_hash() -> Result<()> {
|
pub fn prove_pedersen_hash() -> Result<()> {
|
||||||
let build = Build::new().apply(ctx()?, ())?;
|
let build = (Build {}).apply(context()?, ())?;
|
||||||
let setup = Setup::new(false).apply(ctx()?, build)?;
|
let setup = (Setup { skip_key_check: false }).apply(context()?, build)?;
|
||||||
Prove::new(false).apply(ctx()?, setup.clone())?;
|
(Prove { skip_key_check: false }).apply(context()?, setup.clone())?;
|
||||||
Prove::new(true).apply(ctx()?, setup)?;
|
(Prove { skip_key_check: true }).apply(context()?, setup)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn run_pedersen_hash() -> Result<()> {
|
pub fn run_pedersen_hash() -> Result<()> {
|
||||||
let build = Build::new().apply(ctx()?, ())?;
|
let build = (Build {}).apply(context()?, ())?;
|
||||||
let setup = Setup::new(false).apply(ctx()?, build)?;
|
let setup = (Setup { skip_key_check: false }).apply(context()?, build)?;
|
||||||
let prove = Prove::new(false).apply(ctx()?, setup)?;
|
let prove = (Prove { skip_key_check: false }).apply(context()?, setup)?;
|
||||||
Run::new(false).apply(ctx()?, prove.clone())?;
|
(Run { skip_key_check: false }).apply(context()?, prove.clone())?;
|
||||||
Run::new(true).apply(ctx()?, prove)?;
|
(Run { skip_key_check: true }).apply(context()?, prove)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,14 +75,14 @@ pub fn test_pedersen_hash() -> Result<()> {
|
|||||||
let mut main_file = PathBuf::from(PEDERSEN_HASH_PATH);
|
let mut main_file = PathBuf::from(PEDERSEN_HASH_PATH);
|
||||||
main_file.push("src/main.leo");
|
main_file.push("src/main.leo");
|
||||||
|
|
||||||
Test::new(Vec::new()).apply(ctx()?, ())?;
|
(Test { files: vec![] }).apply(context()?, ())?;
|
||||||
Test::new(vec![main_file]).apply(ctx()?, ())?;
|
(Test { files: vec![main_file] }).apply(context()?, ())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_logout() -> Result<()> {
|
pub fn test_logout() -> Result<()> {
|
||||||
Logout::new().apply(ctx()?, ())?;
|
(Logout {}).apply(context()?, ())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,19 +91,19 @@ pub fn test_logout() -> Result<()> {
|
|||||||
#[test]
|
#[test]
|
||||||
pub fn login_incorrect_credentials_or_token() -> Result<()> {
|
pub fn login_incorrect_credentials_or_token() -> Result<()> {
|
||||||
// no credentials passed
|
// no credentials passed
|
||||||
let login = Login::new(None, None, None).apply(ctx()?, ());
|
let login = Login::new(None, None, None).apply(context()?, ());
|
||||||
assert!(login.is_err());
|
assert!(login.is_err());
|
||||||
|
|
||||||
// incorrect token
|
// incorrect token
|
||||||
let login = Login::new(Some("none".to_string()), None, None).apply(ctx()?, ());
|
let login = Login::new(Some("none".to_string()), None, None).apply(context()?, ());
|
||||||
assert!(login.is_err());
|
assert!(login.is_err());
|
||||||
|
|
||||||
// only user, no pass
|
// only user, no pass
|
||||||
let login = Login::new(None, Some("user".to_string()), None).apply(ctx()?, ());
|
let login = Login::new(None, Some("user".to_string()), None).apply(context()?, ());
|
||||||
assert!(login.is_err());
|
assert!(login.is_err());
|
||||||
|
|
||||||
// no user, only pass
|
// no user, only pass
|
||||||
let login = Login::new(None, None, Some("pass".to_string())).apply(ctx()?, ());
|
let login = Login::new(None, None, Some("pass".to_string())).apply(context()?, ());
|
||||||
assert!(login.is_err());
|
assert!(login.is_err());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -111,20 +111,48 @@ pub fn login_incorrect_credentials_or_token() -> Result<()> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn leo_update_and_update_automatic() -> Result<()> {
|
pub fn leo_update_and_update_automatic() -> Result<()> {
|
||||||
Update::new(true, true, None).apply(ctx()?, ())?;
|
let update = Update {
|
||||||
Update::new(false, true, None).apply(ctx()?, ())?;
|
list: true,
|
||||||
Update::new(false, false, None).apply(ctx()?, ())?;
|
studio: true,
|
||||||
|
automatic: None,
|
||||||
|
};
|
||||||
|
update.apply(context()?, ())?;
|
||||||
|
|
||||||
Update::new(false, false, Some(UpdateAutomatic::Automatic { value: true })).apply(ctx()?, ())?;
|
let update = Update {
|
||||||
Update::new(false, false, Some(UpdateAutomatic::Automatic { value: false })).apply(ctx()?, ())?;
|
list: false,
|
||||||
|
studio: true,
|
||||||
|
automatic: None,
|
||||||
|
};
|
||||||
|
update.apply(context()?, ())?;
|
||||||
|
|
||||||
|
let update = Update {
|
||||||
|
list: false,
|
||||||
|
studio: false,
|
||||||
|
automatic: None,
|
||||||
|
};
|
||||||
|
update.apply(context()?, ())?;
|
||||||
|
|
||||||
|
let update = Update {
|
||||||
|
list: false,
|
||||||
|
studio: false,
|
||||||
|
automatic: Some(UpdateAutomatic::Automatic { value: true }),
|
||||||
|
};
|
||||||
|
update.apply(context()?, ())?;
|
||||||
|
|
||||||
|
let update = Update {
|
||||||
|
list: false,
|
||||||
|
studio: false,
|
||||||
|
automatic: Some(UpdateAutomatic::Automatic { value: false }),
|
||||||
|
};
|
||||||
|
update.apply(context()?, ())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create context for Pedersen Hash example
|
/// Create context for Pedersen Hash example
|
||||||
fn ctx() -> Result<Context> {
|
fn context() -> Result<Context> {
|
||||||
let path = PathBuf::from(&PEDERSEN_HASH_PATH);
|
let path = PathBuf::from(&PEDERSEN_HASH_PATH);
|
||||||
let ctx = create_context(path)?;
|
let context = create_context(path)?;
|
||||||
|
|
||||||
Ok(ctx)
|
Ok(context)
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ pub enum PackageError {
|
|||||||
#[error("Failed to initialize package {:?} ({:?})", _0, _1)]
|
#[error("Failed to initialize package {:?} ({:?})", _0, _1)]
|
||||||
FailedToInitialize(String, OsString),
|
FailedToInitialize(String, OsString),
|
||||||
|
|
||||||
|
#[error("Invalid project name: {:?}", _0)]
|
||||||
|
InvalidPackageName(String),
|
||||||
|
|
||||||
#[error("`{}` metadata: {}", _0, _1)]
|
#[error("`{}` metadata: {}", _0, _1)]
|
||||||
Removing(&'static str, io::Error),
|
Removing(&'static str, io::Error),
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,9 @@ use std::io;
|
|||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ManifestError {
|
pub enum ManifestError {
|
||||||
|
#[error("{}: {}", _0, _1)]
|
||||||
|
Crate(&'static str, String),
|
||||||
|
|
||||||
#[error("`{}` creating: {}", _0, _1)]
|
#[error("`{}` creating: {}", _0, _1)]
|
||||||
Creating(&'static str, io::Error),
|
Creating(&'static str, io::Error),
|
||||||
|
|
||||||
@ -36,3 +39,9 @@ pub enum ManifestError {
|
|||||||
#[error("`{}` writing: {}", _0, _1)]
|
#[error("`{}` writing: {}", _0, _1)]
|
||||||
Writing(&'static str, io::Error),
|
Writing(&'static str, io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<crate::errors::PackageError> for ManifestError {
|
||||||
|
fn from(error: crate::errors::PackageError) -> Self {
|
||||||
|
ManifestError::Crate("leo-package", error.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -37,6 +37,11 @@ impl LeoPackage {
|
|||||||
package::Package::initialize(package_name, is_lib, path)
|
package::Package::initialize(package_name, is_lib, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the given Leo package name is valid.
|
||||||
|
pub fn is_package_name_valid(package_name: &str) -> bool {
|
||||||
|
package::Package::is_package_name_valid(package_name)
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes an imported Leo package
|
/// Removes an imported Leo package
|
||||||
pub fn remove_imported_package(package_name: &str, path: &Path) -> Result<(), PackageError> {
|
pub fn remove_imported_package(package_name: &str, path: &Path) -> Result<(), PackageError> {
|
||||||
package::Package::remove_imported_package(package_name, path)
|
package::Package::remove_imported_package(package_name, path)
|
||||||
|
@ -34,17 +34,79 @@ pub struct Package {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Package {
|
impl Package {
|
||||||
pub fn new(package_name: &str) -> Self {
|
pub fn new(package_name: &str) -> Result<Self, PackageError> {
|
||||||
Self {
|
// Check that the package name is valid.
|
||||||
|
if !Self::is_package_name_valid(package_name) {
|
||||||
|
return Err(PackageError::InvalidPackageName(package_name.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
name: package_name.to_owned(),
|
name: package_name.to_owned(),
|
||||||
version: "0.1.0".to_owned(),
|
version: "0.1.0".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
license: None,
|
license: None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the package name is valid.
|
||||||
|
///
|
||||||
|
/// Package names must be lowercase and composed solely
|
||||||
|
/// of ASCII alphanumeric characters, and may be word-separated
|
||||||
|
/// by a single dash '-'.
|
||||||
|
pub fn is_package_name_valid(package_name: &str) -> bool {
|
||||||
|
// Check that the package name is nonempty.
|
||||||
|
if package_name.is_empty() {
|
||||||
|
tracing::error!("Project names must be nonempty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut previous = package_name.chars().next().unwrap();
|
||||||
|
|
||||||
|
// Check that the first character is not a dash.
|
||||||
|
if previous == '-' {
|
||||||
|
tracing::error!("Project names cannot begin with a dash");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate and check that the package name is valid.
|
||||||
|
for current in package_name.chars() {
|
||||||
|
// Check that the package name is lowercase.
|
||||||
|
if !current.is_ascii_lowercase() && current != '-' {
|
||||||
|
tracing::error!("Project names must be all lowercase");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the package name is only ASCII alphanumeric or a dash.
|
||||||
|
if !current.is_ascii_alphanumeric() && current != '-' {
|
||||||
|
tracing::error!("Project names must be ASCII alphanumeric, and may be word-separated with a dash");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the previous character was a dash, check that the current character is not a dash.
|
||||||
|
if previous == '-' && current == '-' {
|
||||||
|
tracing::error!("Project names may only be word-separated by one dash");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the last character is not a dash.
|
||||||
|
if previous == '-' {
|
||||||
|
tracing::error!("Project names cannot end with a dash");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if a package is can be initialized at a given path.
|
/// Returns `true` if a package is can be initialized at a given path.
|
||||||
pub fn can_initialize(package_name: &str, is_lib: bool, path: &Path) -> bool {
|
pub fn can_initialize(package_name: &str, is_lib: bool, path: &Path) -> bool {
|
||||||
|
// Check that the package name is valid.
|
||||||
|
if !Self::is_package_name_valid(package_name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let mut result = true;
|
let mut result = true;
|
||||||
let mut existing_files = vec![];
|
let mut existing_files = vec![];
|
||||||
|
|
||||||
@ -91,6 +153,11 @@ impl Package {
|
|||||||
|
|
||||||
/// Returns `true` if a package is initialized at the given path
|
/// Returns `true` if a package is initialized at the given path
|
||||||
pub fn is_initialized(package_name: &str, is_lib: bool, path: &Path) -> bool {
|
pub fn is_initialized(package_name: &str, is_lib: bool, path: &Path) -> bool {
|
||||||
|
// Check that the package name is valid.
|
||||||
|
if !Self::is_package_name_valid(package_name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the manifest file exists.
|
// Check if the manifest file exists.
|
||||||
if !Manifest::exists_at(&path) {
|
if !Manifest::exists_at(&path) {
|
||||||
return false;
|
return false;
|
||||||
@ -137,7 +204,7 @@ impl Package {
|
|||||||
// Next, initialize this directory as a Leo package.
|
// Next, initialize this directory as a Leo package.
|
||||||
{
|
{
|
||||||
// Create the manifest file.
|
// Create the manifest file.
|
||||||
Manifest::new(&package_name).write_to(&path)?;
|
Manifest::new(&package_name)?.write_to(&path)?;
|
||||||
|
|
||||||
// Verify that the .gitignore file does not exist.
|
// Verify that the .gitignore file does not exist.
|
||||||
if !Gitignore::exists_at(&path) {
|
if !Gitignore::exists_at(&path) {
|
||||||
@ -190,3 +257,27 @@ impl Package {
|
|||||||
Ok(ImportsDirectory::remove_import(path, package_name)?)
|
Ok(ImportsDirectory::remove_import(path, package_name)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_package_name_valid() {
|
||||||
|
assert!(Package::is_package_name_valid("foo"));
|
||||||
|
assert!(Package::is_package_name_valid("foo-bar"));
|
||||||
|
assert!(Package::is_package_name_valid("foo-bar-baz"));
|
||||||
|
|
||||||
|
assert!(!Package::is_package_name_valid(""));
|
||||||
|
assert!(!Package::is_package_name_valid("-"));
|
||||||
|
assert!(!Package::is_package_name_valid("-foo"));
|
||||||
|
assert!(!Package::is_package_name_valid("-foo-"));
|
||||||
|
assert!(!Package::is_package_name_valid("foo--bar"));
|
||||||
|
assert!(!Package::is_package_name_valid("foo---bar"));
|
||||||
|
assert!(!Package::is_package_name_valid("foo--bar--baz"));
|
||||||
|
assert!(!Package::is_package_name_valid("foo---bar---baz"));
|
||||||
|
assert!(!Package::is_package_name_valid("foo*bar"));
|
||||||
|
assert!(!Package::is_package_name_valid("foo,bar"));
|
||||||
|
assert!(!Package::is_package_name_valid("foo_bar"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -39,11 +39,11 @@ pub struct Manifest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Manifest {
|
impl Manifest {
|
||||||
pub fn new(package_name: &str) -> Self {
|
pub fn new(package_name: &str) -> Result<Self, ManifestError> {
|
||||||
Self {
|
Ok(Self {
|
||||||
project: Package::new(package_name),
|
project: Package::new(package_name)?,
|
||||||
remote: None,
|
remote: None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filename() -> String {
|
pub fn filename() -> String {
|
||||||
|
@ -52,7 +52,10 @@ fn initialize_fails_with_existing_manifest() {
|
|||||||
assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory));
|
assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory));
|
||||||
|
|
||||||
// Manually add a manifest file to the `test_directory`
|
// Manually add a manifest file to the `test_directory`
|
||||||
Manifest::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap();
|
Manifest::new(TEST_PACKAGE_NAME)
|
||||||
|
.unwrap()
|
||||||
|
.write_to(&test_directory)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Attempt to initialize a package at the `test_directory`
|
// Attempt to initialize a package at the `test_directory`
|
||||||
assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err());
|
assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err());
|
||||||
|
Loading…
Reference in New Issue
Block a user