├── .art └── settings.toml ├── .gitignore ├── .pylintrc ├── .travis.yml ├── CONTRIBUTORS.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── artifact-app ├── Cargo.toml ├── build.rs ├── src │ ├── bin │ │ └── art.rs │ ├── check.rs │ ├── data │ │ ├── purpose.md │ │ └── settings.toml │ ├── dev_prelude.rs │ ├── export.rs │ ├── fmt.rs │ ├── frontend.rs │ ├── init.rs │ ├── lib.rs │ ├── ls.rs │ └── serve │ │ ├── handler.rs │ │ └── mod.rs └── tests │ ├── data_artifact.rs │ ├── data_family.rs │ ├── data_graph.rs │ ├── data_implemented.rs │ ├── data_interop.rs │ ├── data_name.rs │ ├── data_raw.rs │ ├── data_raw_names.rs │ ├── lib_ser.rs │ └── serve_interop.rs ├── artifact-data ├── .art │ └── settings.toml ├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT └── src │ ├── artifact.rs │ ├── dev_prelude.rs │ ├── graph.rs │ ├── implemented.rs │ ├── intermediate.rs │ ├── lib.rs │ ├── modify.rs │ ├── project.rs │ ├── raw.rs │ ├── raw_names.rs │ └── settings.rs ├── artifact-frontend ├── .gitignore ├── Cargo.toml ├── shell.nix ├── src │ ├── artifact.rs │ ├── dev_prelude.rs │ ├── edit.rs │ ├── example.rs │ ├── fetch.rs │ ├── graph.rs │ ├── main.rs │ ├── name.rs │ ├── nav.rs │ └── view.rs └── static │ ├── ace.min.css │ ├── commonmark.min.js │ ├── fontawesome-all.js │ ├── index.html │ ├── initial.json │ ├── styles.css │ └── viz-lite.js ├── artifact-lib ├── .gitignore ├── Cargo.toml └── src │ ├── dev_prelude.rs │ ├── expected.rs │ └── lib.rs ├── artifact-ser ├── .gitignore ├── Cargo.toml └── src │ ├── dev_prelude.rs │ ├── expand_names.rs │ ├── family.rs │ ├── lib.rs │ ├── lint.rs │ ├── markdown.rs │ ├── md_graph.rs │ ├── name.rs │ └── ser.rs ├── artifact-test ├── .gitignore ├── Cargo.toml ├── README.md ├── interop_tests │ ├── basic │ │ ├── .art │ │ │ └── settings.toml │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── assert-cases │ │ │ └── basic │ │ │ │ ├── assert_load_lints.yaml │ │ │ │ ├── assert_project.yaml │ │ │ │ └── assert_project_lints.yaml │ │ ├── build.rs │ │ ├── design │ │ │ ├── foo.md │ │ │ └── purpose.md │ │ └── src │ │ │ ├── baz.rs │ │ │ ├── foo │ │ │ ├── fab.rs │ │ │ ├── mod.rs │ │ │ └── test.rs │ │ │ └── lib.rs │ ├── design_only │ │ ├── .art │ │ │ └── settings.toml │ │ ├── assert-cases │ │ │ ├── basic │ │ │ │ ├── assert_load_lints.yaml │ │ │ │ └── assert_project.yaml │ │ │ ├── delete │ │ │ │ ├── assert_load_lints.yaml │ │ │ │ ├── assert_project.yaml │ │ │ │ └── modify.yaml │ │ │ ├── multi │ │ │ │ ├── assert_load_lints.yaml │ │ │ │ ├── assert_project.yaml │ │ │ │ └── modify.yaml │ │ │ ├── overlap │ │ │ │ ├── assert_modify_fail.yaml │ │ │ │ └── modify.yaml │ │ │ ├── update-dne │ │ │ │ ├── assert_modify_fail.yaml │ │ │ │ └── modify.yaml │ │ │ ├── update-invalid-id │ │ │ │ ├── assert_modify_fail.yaml │ │ │ │ └── modify.yaml │ │ │ └── update │ │ │ │ ├── assert_load_lints.yaml │ │ │ │ ├── assert_project.yaml │ │ │ │ └── modify.yaml │ │ └── design │ │ │ └── purpose.md │ ├── empty │ │ ├── .art │ │ │ └── settings.toml │ │ ├── assert-cases │ │ │ ├── basic │ │ │ │ ├── assert_load_lints.yaml │ │ │ │ ├── assert_project.yaml │ │ │ │ └── assert_project_lints.yaml │ │ │ └── create-one │ │ │ │ ├── assert_load_lints.yaml │ │ │ │ ├── assert_project.yaml │ │ │ │ ├── assert_project_lints.yaml │ │ │ │ └── modify.yaml │ │ └── design │ │ │ └── .empty │ ├── lints │ │ ├── .art │ │ │ └── settings.toml │ │ ├── assert-cases │ │ │ └── basic │ │ │ │ └── assert_project_lints.yaml │ │ ├── design │ │ │ ├── purpose.md │ │ │ └── text.toml │ │ └── src │ │ │ └── lib.rs │ ├── lints2 │ │ ├── .art │ │ │ └── settings.toml │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── assert-cases │ │ │ └── basic │ │ │ │ ├── assert_load_lints.yaml │ │ │ │ ├── assert_project.yaml │ │ │ │ └── assert_project_lints.yaml │ │ ├── design │ │ │ └── purpose.md │ │ ├── src │ │ │ └── lib.rs │ │ └── target │ │ │ ├── .rustc_info.json │ │ │ └── debug │ │ │ ├── .cargo-lock │ │ │ ├── build │ │ │ └── basic-2ccdec1e4884b553 │ │ │ │ └── build_script_build-2ccdec1e4884b553.d │ │ │ └── incremental │ │ │ └── build_script_build-2mpg4k3gfwhp5 │ │ │ └── s-f2qdvys262-ewn7ea.lock │ ├── settings │ │ ├── .art │ │ │ └── settings.toml │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── assert-cases │ │ │ └── basic │ │ │ │ ├── assert_load_lints.yaml │ │ │ │ ├── assert_project.yaml │ │ │ │ └── assert_project_lints.yaml │ │ ├── build.rs │ │ ├── design │ │ │ ├── foo.md │ │ │ └── purpose.md │ │ ├── exported.md │ │ └── src │ │ │ ├── baz.rs │ │ │ ├── foo │ │ │ ├── fab.rs │ │ │ ├── mod.rs │ │ │ └── test.rs │ │ │ └── lib.rs │ ├── source_invalid │ │ ├── .art │ │ │ └── settings.toml │ │ ├── assert-cases │ │ │ └── basic │ │ │ │ └── assert_load_lints.yaml │ │ └── src │ │ │ ├── one.py │ │ │ ├── two-b.py │ │ │ └── two.py │ └── source_only │ │ ├── .art │ │ └── settings.toml │ │ ├── assert-cases │ │ └── basic │ │ │ └── assert_project.yaml │ │ ├── pylib │ │ ├── __init__.py │ │ ├── example.py │ │ ├── noinclude.py │ │ └── noinclude │ │ │ └── foo.py │ │ └── src │ │ └── lib.rs └── src │ ├── artifact.rs │ ├── dev_prelude.rs │ ├── family.rs │ ├── framework.rs │ ├── graph.rs │ ├── implemented.rs │ ├── lib.rs │ ├── name.rs │ ├── raw.rs │ └── raw_names.rs ├── book ├── .gitignore ├── book.toml └── src │ ├── Addendum.md │ ├── ArtifactIntro.md │ ├── BestPractices.md │ ├── CheatSheet.md │ ├── CleaningUp.md │ ├── Design.md │ ├── DetailedDesign.md │ ├── ExampleFile.md │ ├── ExportingHtml.md │ ├── FAQ.md │ ├── Feedback.md │ ├── Finishing.md │ ├── GettingStarted.md │ ├── Implementation.md │ ├── Installation.md │ ├── Introduction.md │ ├── License.md │ ├── Purpose.md │ ├── PurposeArtifact.md │ ├── QuickStart.md │ ├── RunningTests.md │ ├── SPECIFICATION.md │ ├── SUMMARY.md │ ├── SimpleQuality.md │ ├── StartingProject.md │ ├── TODO.md │ ├── Tools.md │ ├── Vocabulary.md │ ├── WebUi.md │ ├── data │ ├── artifact-thumb.png │ ├── attribution │ │ ├── Attribution.md │ │ └── b0rk-design-documents.jpg-large │ ├── example-hello.png │ ├── quickstart │ │ ├── images.xcf │ │ ├── text-REQ-purpose.png │ │ ├── text-req-parts.png │ │ ├── web-create-btn.png │ │ ├── web-create.png │ │ ├── web-edit-btn.png │ │ ├── web-edit.png │ │ ├── web-implemented-link.png │ │ ├── web-save-btn.png │ │ ├── web-select.png │ │ ├── web-source-code.png │ │ └── web-spc-world-done.png │ └── web-ui.png │ ├── examples │ ├── part1 │ │ ├── ace.min.css │ │ ├── artifact-frontend.js │ │ ├── artifact-frontend.wasm │ │ ├── commonmark.min.js │ │ ├── fontawesome-all.js │ │ ├── index.html │ │ ├── initial.json │ │ ├── styles.css │ │ └── viz-lite.js │ └── part2 │ │ ├── ace.min.css │ │ ├── artifact-frontend.js │ │ ├── artifact-frontend.wasm │ │ ├── commonmark.min.js │ │ ├── fontawesome-all.js │ │ ├── index.html │ │ ├── initial.json │ │ ├── styles.css │ │ └── viz-lite.js │ └── logo │ ├── logo-logo.png │ ├── logo-medium.png │ ├── logo-small.png │ └── logo.png ├── ci ├── before_deploy.ps1 ├── before_deploy.sh ├── data │ ├── artifact-thumb.png │ ├── attribution │ │ ├── Attribution.md │ │ └── b0rk-design-documents.jpg-large │ ├── exported.md │ └── logo │ │ ├── logo-logo.png │ │ ├── logo-medium.png │ │ ├── logo-small.png │ │ └── logo.png ├── install.sh └── script.sh ├── design ├── cli.md ├── data │ ├── artifact.md │ ├── cache.md │ ├── family.md │ ├── implemented.md │ ├── modify.md │ ├── name.md │ ├── purpose.md │ ├── raw.md │ └── structs.md └── purpose.md ├── justfile └── scripts ├── .gitignore ├── db.dump ├── interact.py ├── lic_header.txt ├── license.py └── requirements.txt /.art/settings.toml: -------------------------------------------------------------------------------- 1 | artifact_paths = ["{repo}/design"] 2 | 3 | exclude_artifact_paths = [] 4 | 5 | code_paths = [ 6 | "/artifact-app/src", 7 | "/artifact-app/tests", 8 | "/artifact-lib/src", 9 | "/artifact-ser/src", 10 | "/artifact-data/src", 11 | "/artifact-test/src", 12 | "/artifact-frontend/src", 13 | ] 14 | 15 | exclude_code_paths = [ 16 | ] 17 | 18 | code_url = "https://github.com/vitiral/artifact/blob/master/{file}#L{line}" 19 | 20 | [export] 21 | md_header = """ 22 | Artifact design docs, exported to markdown. 23 | 24 | See [REQ-purpose](#REQ-PURPOSE) for the top level artifact. 25 | 26 | > Note: Export docs like this with `art export md exported.md` 27 | > 28 | > Settings are in `.art/settings.toml` 29 | """ 30 | md_family = { type = "list" } 31 | 32 | [export.md_dot] 33 | type = "ignore" 34 | # pre = """ 35 | # ![Alt text](https://g.gravizo.com/source/custom_mark10?https%3A%2F%2Fraw.githubusercontent.com%2FTLmaK0%2Fgravizo%2Fmaster%2FREADME.md) 36 | #
37 | # 38 | # custom_mark10 39 | # """ 40 | # post = """ 41 | # custom_mark10 42 | #
43 | # """ 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /gh-pages 2 | # Generated by Cargo 3 | # will have compiled files and executables 4 | /target/ 5 | /target-install/ 6 | .cache 7 | *.log 8 | node_modules 9 | *.ropeproject 10 | result 11 | *.proptest-regressions 12 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | [MESSAGES CONTROL] 2 | disable=locally-disabled,too-few-public-methods,invalid-name,too-many-statements,too-many-public-methods,too-many-instance-attributes,redefined-builtin,too-many-arguments 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: rust 3 | rust: stable 4 | services: docker 5 | sudo: required 6 | os: 7 | - linux 8 | - osx 9 | - windows 10 | 11 | env: 12 | global: 13 | - CRATE_NAME=artifact 14 | matrix: 15 | allow_failures: 16 | - os: windows 17 | 18 | before_install: 19 | - set -e 20 | - export RUST_BACKTRACE=1 21 | - export TARGET=$(rustup target list | grep '(default)' | awk '{print $1}') 22 | - export BTOOL=cargo 23 | - export RELEASE_NAME="$CRATE_NAME-$TRAVIS_TAG-$TARGET" 24 | - echo TARGET=$TARGET 25 | - echo RELEASE_NAME=$RELEASE_NAME 26 | - rustup self update 27 | 28 | install: 29 | - sh ci/install.sh 30 | - source ~/.cargo/env || true 31 | 32 | script: 33 | - bash ci/script.sh 34 | 35 | after_script: set +e 36 | before_deploy: 37 | - sh ci/before_deploy.sh 38 | 39 | deploy: 40 | provider: releases 41 | api_key: 42 | secure: JtkWm1okExxwWghT6GijjEYD2ORjWb3hlvfLxH6VNt00r22G8yo/XxYdwKrFEsRv1sg0BajUl3/RzXmTYxXtRDVwoyFi7+pAEsuJ17Z+/zZtEZwoomZLJVmJUgMNOOg0zW01qPGSYmgi2gtuXgNBWjasGlVzrNu/xoyr0Y+J0U6bVawbvr++ZnzeY8tbB7XZvonDPCcXjShTZuA7hCaqUKvj+GxrO1kCejJTW4R4pq1jQNsmavlHQi6w797dasX0ag18lIAvKMEMP+d+9AJ4qXA/pwFUwDw1pQe/ZeU9Cuv/bJoAtz27Fq4T18dFHpST4pwq3JmpgSE/zo87s3Kj53fu9Uobew4VzMjti0HH/0sIyoWpWV//feIrBAbPrRq6oIABXRTaiCTlGJqwt718aQM0v2jAGl1q2SeKOtgX3AMrP2a2MHMEiGuvFQJilqcwofzTjJJJp2C8asax1hVJpcB5NhPZ7xayzmDBA0x7zOD3h1v6uprfuyYmWKoiASWYiULlDbVme8n+worXhPcFkpCr7l97D/1CREKDvXTQF+7CcB5XRADKwifzqU+XYWA+vrQ+H+/TzwbCAIYIdkp5DBFPl7PdePD1QFIaJ7YDLpwzy7oyz7pGblu9tNqjLjnZxvbgO/mHpWTNTOq9D3O9ecxqjXfmY3cjp6RTf7IEtfs= 43 | file_glob: true 44 | file: $RELEASE_NAME.* 45 | on: 46 | repo: vitiral/artifact 47 | condition: $TRAVIS_RUST_VERSION = stable 48 | tags: true 49 | skip_cleanup: true 50 | 51 | cache: cargo 52 | before_cache: 53 | - chmod -R a+r $HOME/.cargo 54 | 55 | branches: 56 | only: 57 | - /^v\d+\.\d+\.\d+$/ 58 | - master 59 | 60 | notifications: 61 | email: 62 | on_success: never 63 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | ## Contributors 2 | **[Chat on gitter](https://gitter.im/artifact-app/Lobby)** 3 | 4 | To set up a build environment and run tests, simply run: 5 | 6 | ```bash 7 | git clone git@github.com:vitiral/artifact.git && cd artifact 8 | source env # installs environment to `target/env` 9 | just test-all 10 | ``` 11 | 12 | Note: `source env` will take a while as it (locally) installs 13 | build/test/lint/fmt toolchains for rust, node.js and python from scratch. It 14 | does not touch ANYTHING in your global environment. 15 | 16 | A quick source code overview: 17 | - `justfile` contains build/test/etc scripts 18 | - design documents are in `design/` 19 | - rust source code is in `src/` 20 | - elm source code (html frontend) is in `web-ui/src/` 21 | - selenium (end-to-end web) tests are in `web-ui/sel_tests/` 22 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | "artifact-ser", 5 | "artifact-lib", 6 | "artifact-data", 7 | "artifact-app", 8 | "artifact-frontend", 9 | "artifact-test", 10 | ] 11 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Garrett Berg, vitiral@gmail.com 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Garrett Berg, vitiral@gmail.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /artifact-app/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Garrett Berg "] 3 | description = """ 4 | Artifact is a design doc tool made for developers. It allows anyone to 5 | easily write and link their design docs both to each other and to source code, 6 | making it easy to track how complete their project is. 7 | Documents are revision controllable, can be rendered as a static 8 | web page and have a full suite of command line tools for searching, 9 | formatting and displaying them. 10 | """ 11 | documentation = "http://vitiral.github.io/artifact/" 12 | keywords = [ 13 | "cmdline", 14 | "tool", 15 | "requirements", 16 | "documentation", 17 | "testing", 18 | ] 19 | license = "MIT OR Apache-2.0" 20 | name = "artifact-app" 21 | readme = "README.md" 22 | repository = "https://github.com/vitiral/artifact" 23 | version = "2.1.5" 24 | build = "build.rs" 25 | edition = "2018" 26 | 27 | [dependencies] 28 | difference = "2.0.0" 29 | ergo = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 30 | serde = "1.0.66" 31 | serde_derive = "1.0.66" 32 | termstyle = "0.1.2" 33 | expect_macro = "0.2.1" 34 | nickel = "0.10" 35 | # nickel = { git = "https://github.com/nickel-org/nickel.rs" } 36 | jsonrpc-core = "8.0.1" 37 | artifact_data = {path = "../artifact-data"} 38 | artifact_lib = {path = "../artifact-lib"} 39 | artifact_ser = {path = "../artifact-ser"} 40 | jrpc = "0.4.0" 41 | quicli = "0.3.0" 42 | 43 | # [dependencies.quicli] 44 | # path = "quicli" 45 | # default-features = false 46 | 47 | [dev-dependencies] 48 | assert_cli = "0.6.1" 49 | reqwest = "0.9.11" 50 | pretty_assertions = "0.5.1" 51 | artifact_test = { path = "../artifact-test" } 52 | 53 | [build-dependencies] 54 | ergo = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 55 | -------------------------------------------------------------------------------- /artifact-app/build.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate ergo; 3 | use ergo::*; 4 | use std::process::Command; 5 | 6 | fn main() { 7 | println!("Build Script Started"); 8 | check_deps(); 9 | // build_frontend(); 10 | build_mdbook(); 11 | cp_mdbook(); 12 | tar_frontend().expect("tarring frontend failed"); 13 | } 14 | 15 | lazy_static! { 16 | static ref WORKSPACE: PathDir = PathDir::new("..").unwrap(); 17 | static ref FRONTEND: PathDir = PathDir::new("../artifact-frontend").unwrap(); 18 | static ref BOOK: PathDir = PathDir::new("../book").unwrap(); 19 | static ref TARGET: PathDir = PathDir::create_all(WORKSPACE.join("target")).unwrap(); 20 | static ref FRONTEND_DEPLOY: PathDir = PathDir::create_all(TARGET.join("deploy")).unwrap(); 21 | } 22 | 23 | fn check_deps() { 24 | println!("Checking dependencies"); 25 | 26 | let mut missing = Vec::new(); 27 | 28 | let check_cmd = |m: &mut Vec<_>, cmd: &'static str| { 29 | let is_ok = Command::new("which") 30 | .args(&[cmd]) 31 | .output() 32 | .expect("which/where doesn't exist") 33 | .status 34 | .success(); 35 | 36 | if !is_ok { 37 | m.push(cmd); 38 | } 39 | }; 40 | 41 | check_cmd(&mut missing, "mdbook"); 42 | 43 | if !missing.is_empty() { 44 | println!("ERROR: Missing binary dependencies, their binaries must be put in target/deps/"); 45 | for c in missing { 46 | println!(" {}", c); 47 | } 48 | ::std::process::exit(1); 49 | } else { 50 | println!("- All dependencies found"); 51 | } 52 | } 53 | 54 | fn build_mdbook() { 55 | println!("Building the book"); 56 | let _status = Command::new("mdbook") 57 | .current_dir(BOOK.as_path()) 58 | .args(&["build"]) 59 | .status() 60 | .unwrap(); 61 | } 62 | 63 | fn cp_mdbook() { 64 | println!("Copying mdbook to deploy"); 65 | let (send, recv) = ch::unbounded(); 66 | let deploy = PathDir::create_all(FRONTEND_DEPLOY.join("docs")).unwrap(); 67 | deploy.clone().remove_all().unwrap(); 68 | deep_copy( 69 | send, 70 | PathDir::new(BOOK.join("out").join("book")).unwrap(), 71 | deploy, 72 | ); 73 | let errs: Vec<_> = recv.into_iter().collect(); 74 | assert!(errs.is_empty(), "{:?}", errs); 75 | } 76 | 77 | // fn build_frontend() { 78 | // println!("Building artifact-frontend"); 79 | // let status = Command::new("cargo-web") 80 | // .current_dir(WORKSPACE.as_path()) 81 | // .args(&[ 82 | // "deploy", 83 | // "-p", 84 | // "artifact-frontend", 85 | // "--target=wasm32-unknown-unknown", 86 | // "--release", 87 | // ]) 88 | // .status() 89 | // .unwrap(); 90 | // 91 | // assert!(status.success(), "artifact-frontend failed to build"); 92 | // } 93 | 94 | fn tar_frontend() -> ::std::io::Result { 95 | let target = PathDir::new(WORKSPACE.join("target"))?; 96 | let deploy = match PathDir::new(target.join("deploy")) { 97 | Ok(d) => d, 98 | Err(e) => panic!("target/deploy doesn't exist. justfile::build-frontend defines how."), 99 | }; 100 | let archive_path = PathFile::create(target.join("frontend.tar"))?; 101 | 102 | println!("Taring frontend {:?} into {:?}", deploy, archive_path); 103 | let mut f = FileWrite::create(&archive_path)?; 104 | let mut builder = tar::Builder::new(&mut f); 105 | 106 | tar_dir(&deploy, &deploy, &mut builder)?; 107 | 108 | builder.finish()?; 109 | 110 | Ok(archive_path) 111 | } 112 | 113 | fn tar_dir( 114 | prefix: &PathDir, 115 | from: &PathDir, 116 | builder: &mut tar::Builder, 117 | ) -> ::std::io::Result<()> { 118 | for entry in from.list()? { 119 | let file = match entry.unwrap() { 120 | PathType::File(f) => f, 121 | PathType::Dir(d) => { 122 | tar_dir(prefix, &d, builder); 123 | continue; 124 | } 125 | }; 126 | let mut header = tar::Header::new_old(); 127 | header.set_metadata_in_mode(&file.metadata()?, tar::HeaderMode::Deterministic); 128 | header.set_path(&file.strip_prefix(prefix).unwrap())?; 129 | header.set_cksum(); 130 | let mut r = file.open_read()?; 131 | builder.append(&header, &mut r)?; 132 | } 133 | Ok(()) 134 | } 135 | -------------------------------------------------------------------------------- /artifact-app/src/bin/art.rs: -------------------------------------------------------------------------------- 1 | use artifact_app; 2 | use std::process::exit; 3 | 4 | fn main() { 5 | match artifact_app::run() { 6 | Ok(rc) => exit(rc), 7 | Err(e) => { 8 | eprintln!("{}", e); 9 | exit(1); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /artifact-app/src/check.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! Check for errors 18 | 19 | use crate::dev_prelude::*; 20 | use artifact_data::*; 21 | 22 | #[derive(Debug, StructOpt)] 23 | #[structopt(name = "check")] 24 | /// Check your project for errors and warnings. 25 | pub struct Check { 26 | #[structopt(long = "verbose", short = "v", default_value = "0")] 27 | /// Pass many times for more log output. 28 | pub verbosity: u64, 29 | 30 | #[structopt(long = "work-dir")] 31 | /// Use a different working directory [default: $CWD] 32 | pub work_dir: Option, 33 | } 34 | 35 | /// #SPC-cli.check 36 | pub fn run(cmd: Check) -> Result { 37 | set_log_verbosity!(cmd); 38 | let repo = find_repo(&work_dir!(cmd))?; 39 | info!("Running art-check in repo {}", repo.display()); 40 | let (lints, _) = read_project(repo)?; 41 | if !lints.error.is_empty() { 42 | Err(lints.into()) 43 | } else if !lints.is_empty() { 44 | eprintln!("{}", lints); 45 | Ok(2) // rc=2 if only warnings 46 | } else { 47 | Ok(0) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /artifact-app/src/data/purpose.md: -------------------------------------------------------------------------------- 1 | # REQ-purpose 2 | The goal of this project is... 3 | -------------------------------------------------------------------------------- /artifact-app/src/data/settings.toml: -------------------------------------------------------------------------------- 1 | # ---- Artifact Project Settings ---- 2 | 3 | # Paths containing artifact markdown/toml files 4 | artifact_paths = ["design"] 5 | 6 | # Paths to exclude when loading artifacts 7 | exclude_artifact_paths = [] 8 | 9 | # Paths containing code that has artifact links 10 | code_paths = [] 11 | 12 | # Paths to exclude when searching through code 13 | exclude_code_paths = [] 14 | -------------------------------------------------------------------------------- /artifact-app/src/dev_prelude.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | pub use expect_macro::*; 18 | 19 | pub use artifact_data::ART_DIR; 20 | pub use artifact_lib::*; 21 | #[allow(unused_imports)] 22 | pub use ergo::*; 23 | #[allow(unused_imports)] 24 | pub use quicli::prelude::*; 25 | 26 | #[macro_export] 27 | macro_rules! work_dir { [$cmd:expr] => {{ 28 | match $cmd.work_dir { 29 | Some(ref d) => PathDir::new(d), 30 | None => PathDir::current_dir(), 31 | }? 32 | }}} 33 | 34 | #[macro_export] 35 | macro_rules! set_log_verbosity { [$cmd:expr] => {{ 36 | set_log_verbosity("art", $cmd.verbosity)?; 37 | }}} 38 | 39 | /// Set the logs verbosity based on an integer value: 40 | /// 41 | /// - `0`: error 42 | /// - `1`: warn 43 | /// - `2`: info 44 | /// - `3`: debug 45 | /// - `>=4`: trace 46 | /// 47 | /// This is used in the [`main!`] macro. You should typically use that instead. 48 | /// 49 | /// [`main!`]: macro.main.html 50 | pub fn set_log_verbosity(pkg: &str, verbosity: u64) -> Result<()> { 51 | let log_level = match verbosity { 52 | 0 => LogLevel::Error, 53 | 1 => LogLevel::Warn, 54 | 2 => LogLevel::Info, 55 | 3 => LogLevel::Debug, 56 | _ => LogLevel::Trace, 57 | } 58 | .to_level_filter(); 59 | 60 | LoggerBuilder::new() 61 | .filter(Some(pkg), log_level) 62 | .filter(None, LogLevel::Warn.to_level_filter()) 63 | .try_init()?; 64 | Ok(()) 65 | } 66 | 67 | /// Find the project repo directory. 68 | pub fn find_repo(initial: &PathDir) -> Result { 69 | let mut dir = initial.clone(); 70 | loop { 71 | if dir.concat(ART_DIR)?.exists() { 72 | return Ok(dir); 73 | } 74 | dir = match dir.parent_dir() { 75 | Some(d) => d, 76 | None => bail!("{} not within a directory with `.art`", initial.display()), 77 | }; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /artifact-app/src/fmt.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! Format the project 18 | 19 | use crate::dev_prelude::*; 20 | use artifact_data::*; 21 | 22 | #[derive(Debug, StructOpt)] 23 | #[structopt(name = "fmt")] 24 | /// Format the project and change the filetype. 25 | pub struct Fmt { 26 | #[structopt(long = "verbose", short = "v", default_value = "0")] 27 | /// Pass many times for more log output. 28 | pub verbosity: u64, 29 | 30 | #[structopt(long = "work-dir")] 31 | /// Use a different working directory [default: $CWD] 32 | pub work_dir: Option, 33 | 34 | #[structopt(long = "type")] 35 | /// Set the type of all files 36 | pub ty_: Option, 37 | } 38 | 39 | /// #SPC-cli.fmt 40 | pub fn run(cmd: Fmt) -> Result { 41 | set_log_verbosity!(cmd); 42 | let repo = find_repo(&work_dir!(cmd))?; 43 | info!("Running art-fmt in repo {}", repo.display()); 44 | modify_project(&repo, Vec::new())?; 45 | Ok(0) 46 | } 47 | -------------------------------------------------------------------------------- /artifact-app/src/frontend.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! Helper methods for managing the frontend. 18 | use crate::dev_prelude::*; 19 | 20 | use crate::tar::Archive; 21 | use crate::tempdir::TempDir; 22 | 23 | const WEB_FRONTEND_TAR: &'static [u8] = include_bytes!("../../target/frontend.tar"); 24 | 25 | /// Unpack the web frontend, overriding the initial project settings. 26 | pub(crate) fn unpack_frontend>( 27 | into: P, 28 | init: &ProjectInitialSer, 29 | ) -> ::std::io::Result<()> { 30 | let dir = into.as_ref(); 31 | info!("Unpacking frontend at: {}", dir.display()); 32 | 33 | let mut archive = Archive::new(WEB_FRONTEND_TAR); 34 | archive.unpack(dir)?; 35 | 36 | let init_s = expect!(json::to_string(init)); 37 | 38 | let init_f = PathFile::new(dir.join("initial.json"))?; 39 | init_f.write_str(&init_s)?; 40 | 41 | Ok(()) 42 | } 43 | -------------------------------------------------------------------------------- /artifact-app/src/init.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | 18 | use crate::dev_prelude::*; 19 | use artifact_data::*; 20 | use termstyle::Color::*; 21 | use termstyle::{self, Color, El, Table, Text}; 22 | 23 | #[derive(Debug, StructOpt)] 24 | #[structopt(name = "init", about = "Initialize the directory for artifact.")] 25 | pub struct Init { 26 | #[structopt(long = "verbose", short = "v", default_value = "0")] 27 | /// Pass many times for more log output. 28 | pub verbosity: u64, 29 | 30 | #[structopt(long = "work-dir")] 31 | /// Use a different working directory [default: $CWD] 32 | pub work_dir: Option, 33 | } 34 | 35 | const DESIGN_DIR: &str = "design"; 36 | const PURPOSE_MD: &str = "purpose.md"; 37 | const INIT_SETTINGS_TOML: &str = include_str!("data/settings.toml"); 38 | const INIT_PURPOSE_MD: &str = include_str!("data/purpose.md"); 39 | 40 | /// SPC-cli.init 41 | pub fn run(cmd: Init) -> Result { 42 | set_log_verbosity!(cmd); 43 | let work_dir = work_dir!(cmd); 44 | info!( 45 | "Running art-init in working directory {}", 46 | work_dir.display() 47 | ); 48 | 49 | let art = work_dir.join(ART_DIR); 50 | ensure!( 51 | !art.exists(), 52 | "{} directory already exists at {}", 53 | ART_DIR, 54 | work_dir.display() 55 | ); 56 | let art = PathDir::create(art)?; 57 | let settings = PathFile::create(art.join(SETTINGS_FILE))?; 58 | println!("Created settings file at: {}", settings.display()); 59 | settings.write_str(INIT_SETTINGS_TOML)?; 60 | let design = PathDir::create(work_dir.join(DESIGN_DIR))?; 61 | let purpose = PathFile::create(design.join(PURPOSE_MD))?; 62 | println!("Created initial purpose at: {}", purpose.display()); 63 | purpose.write_str(INIT_PURPOSE_MD)?; 64 | println!( 65 | "Successfully initialized artifact project: {}", 66 | work_dir.display() 67 | ); 68 | Ok(0) 69 | } 70 | -------------------------------------------------------------------------------- /artifact-app/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! The CLI main binary 18 | 19 | #![allow(unused_imports)] 20 | #![allow(dead_code)] 21 | 22 | #[macro_use] 23 | extern crate artifact_data; 24 | 25 | #[macro_use] 26 | extern crate artifact_lib; 27 | 28 | #[allow(unused_imports)] 29 | #[macro_use] 30 | extern crate ergo; 31 | 32 | #[allow(unused_imports)] 33 | #[macro_use] 34 | extern crate quicli; 35 | 36 | #[macro_use] 37 | extern crate expect_macro; 38 | use termstyle; 39 | 40 | use jrpc; 41 | 42 | #[allow(unused_imports)] 43 | use ergo::*; 44 | #[allow(unused_imports)] 45 | use quicli::prelude::*; 46 | 47 | // macro modules must come first 48 | #[macro_use] 49 | mod dev_prelude; 50 | 51 | mod check; 52 | mod export; 53 | mod fmt; 54 | mod frontend; 55 | mod init; 56 | mod ls; 57 | mod serve; 58 | 59 | /// #SPC-cli 60 | pub fn run() -> Result { 61 | use quicli::prelude::structopt::clap::*; 62 | let app = App::new("art") 63 | .author("vitiral") 64 | .version(env!("CARGO_PKG_VERSION")) 65 | .about("Design documentation tool for everybody.") 66 | .subcommand(init::Init::clap()) 67 | .subcommand(check::Check::clap()) 68 | .subcommand(fmt::Fmt::clap()) 69 | .subcommand(ls::Ls::clap()) 70 | .subcommand(serve::Serve::clap()) 71 | .subcommand(export::Export::clap()); 72 | 73 | let matches = app.get_matches(); 74 | 75 | match matches.subcommand() { 76 | ("init", Some(args)) => init::run(init::Init::from_clap(&args)), 77 | ("check", Some(args)) => check::run(check::Check::from_clap(&args)), 78 | ("fmt", Some(args)) => fmt::run(fmt::Fmt::from_clap(&args)), 79 | ("ls", Some(args)) => ls::run(ls::Ls::from_clap(&args)), 80 | ("serve", Some(args)) => serve::run(serve::Serve::from_clap(&args)), 81 | ("export", Some(args)) => export::run(export::Export::from_clap(&args)), 82 | ("", _) => { 83 | eprintln!( 84 | "Error: must specify a subcommand. Use `art help` for a list of subcommands." 85 | ); 86 | Ok(1) 87 | } 88 | (sub, _) => { 89 | eprintln!( 90 | "Error: subcommand '{}' is not valid. Use `art help` for a list of subcommands.", 91 | sub 92 | ); 93 | Ok(1) 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /artifact-app/src/serve/mod.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! #SPC-cli.serve 18 | use std::io; 19 | 20 | use crate::dev_prelude::*; 21 | use artifact_data::*; 22 | 23 | mod handler; 24 | 25 | #[derive(Debug, Default, Clone, StructOpt)] 26 | #[structopt(name = "serve", about = "Serve the web-ui via http.")] 27 | #[cfg_attr(rustfmt, rustfmt_skip)] 28 | pub struct Serve { 29 | #[structopt(long = "verbose", short = "v", parse(from_occurrences))] 30 | /// Pass many times for more log output. 31 | pub verbosity: u64, 32 | 33 | #[structopt(long="work-dir")] 34 | /// Use a different working directory [default: $CWD] 35 | pub work_dir: Option, 36 | 37 | /// Select the port to serve on. 38 | #[structopt(default_value="5373")] 39 | pub port: u64, 40 | } 41 | 42 | lazy_static! { 43 | static ref LOCKED: Mutex> = Mutex::new(None); 44 | } 45 | 46 | /// Run the `art serve` command 47 | pub fn run(cmd: Serve) -> Result { 48 | set_log_verbosity!(cmd); 49 | let repo = find_repo(&work_dir!(cmd))?; 50 | info!("Running art-serve in repo {}", repo.display()); 51 | 52 | let (lints, project) = read_project(repo)?; 53 | { 54 | let mut locked = LOCKED.lock().unwrap(); 55 | *locked = Some(ProjectResult { 56 | project: project, 57 | lints: lints, 58 | }); 59 | } 60 | 61 | handler::start_api(cmd); 62 | Ok(0) 63 | } 64 | -------------------------------------------------------------------------------- /artifact-app/tests/data_artifact.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! Unit/Fuzz Tests: 18 | //! - #TST-unit.artifact 19 | //! - #TST-fuzz.artifact 20 | 21 | use artifact_data::artifact; 22 | use artifact_test::dev_prelude::*; 23 | 24 | #[test] 25 | fn sanity_determine_partofs() { 26 | fn with_partof(mut partof: Vec) -> ArtifactIm { 27 | partof.sort(); 28 | ArtifactIm { 29 | name: name!("TST-fake"), 30 | file: PathSer::from("/fake"), 31 | partof: partof.drain(..).collect(), 32 | done: None, 33 | text: "".into(), 34 | } 35 | } 36 | 37 | let arts = indexmap! { 38 | name!("REQ-aaa") => with_partof(vec![]), 39 | // test auto-parent 40 | name!("REQ-aaa-a") => with_partof(vec![]), 41 | // test auto-partof (no parent) 42 | name!("SPC-aaa-a") => with_partof(vec![]), 43 | name!("SPC-bbb") => with_partof(vec![]), 44 | // test explcit-link + parent 45 | name!("SPC-bbb-p") => with_partof(vec![name!("REQ-aaa")]), 46 | // test explcit-link only 47 | name!("SPC-ccc") => with_partof(vec![name!("REQ-aaa")]), 48 | }; 49 | 50 | let mut partofs = artifact::determine_partofs(&arts); 51 | let mut expected = indexmap! { 52 | name!("REQ-aaa") => indexset![], 53 | name!("REQ-aaa-a") => indexset![name!("REQ-aaa")], 54 | name!("SPC-aaa-a") => indexset![name!("REQ-aaa-a")], 55 | name!("SPC-bbb") => indexset![], 56 | name!("SPC-bbb-p") => indexset![name!("SPC-bbb"), name!("REQ-aaa")], 57 | name!("SPC-ccc") => indexset![name!("REQ-aaa")], 58 | }; 59 | partofs.sort_keys(); 60 | expected.sort_keys(); 61 | assert_eq!(expected, partofs); 62 | } 63 | -------------------------------------------------------------------------------- /artifact-app/tests/data_interop.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! Interop Tests: 18 | //! - #TST-read-artifact 19 | #[macro_use] 20 | extern crate expect_macro; 21 | use artifact_data; 22 | 23 | use artifact_lib::*; 24 | use artifact_test::{ 25 | assert_stuff_data, run_generic_interop_test, run_generic_interop_tests, INTEROP_TESTS_PATH, 26 | }; 27 | use ergo::*; 28 | 29 | /// This runs the interop tests for artifact-data. 30 | fn run_interop_tests>(test_base: P) { 31 | run_generic_interop_tests(test_base, run_data_test); 32 | } 33 | 34 | fn run_data_test(project_path: PathDir) { 35 | run_generic_interop_test( 36 | project_path, 37 | (), 38 | read_project_shim, 39 | modify_project_shim, 40 | assert_stuff_data, 41 | ); 42 | } 43 | 44 | /// Simply calls `artifact_data::read_project(project_path)` 45 | /// 46 | /// Used to satisfy the type requirements of `Fn` (cannot accept `AsRef`) 47 | fn read_project_shim( 48 | project_path: PathDir, 49 | _state: (), 50 | ) -> Result<(lint::Categorized, Project), lint::Categorized> { 51 | artifact_data::read_project(project_path) 52 | } 53 | 54 | /// Simply calls `artifact_data::modify_project(project_path, operations)` 55 | /// 56 | /// Used to satisfy the type requirements of `Fn` (cannot accept `AsRef`) 57 | fn modify_project_shim( 58 | project_path: PathDir, 59 | operations: Vec, 60 | _state: (), 61 | ) -> Result<(lint::Categorized, Project), ModifyError> { 62 | // Do basic round-trip serialization 63 | let result = expect!(round_ser!(Vec, operations)); 64 | assert_eq!(operations, result); 65 | 66 | // Do round trip through `*Ser` types 67 | let operations_ser = expect!(round_ser!(Vec, operations)); 68 | let _result = expect!(round_ser!(Vec, operations_ser)); 69 | 70 | artifact_data::modify_project(project_path, operations) 71 | } 72 | 73 | #[test] 74 | /// #TST-read-artifact.empty 75 | fn data_interop_project_empty() { 76 | run_interop_tests(INTEROP_TESTS_PATH.join("empty")); 77 | } 78 | 79 | #[test] 80 | /// #TST-read-artifact.source_only 81 | fn data_interop_source_only() { 82 | run_interop_tests(INTEROP_TESTS_PATH.join("source_only")); 83 | } 84 | 85 | #[test] 86 | /// #TST-read-artifact.source_invalid 87 | fn data_interop_source_invalid() { 88 | run_interop_tests(INTEROP_TESTS_PATH.join("source_invalid")); 89 | } 90 | 91 | #[test] 92 | /// #TST-read-artifact.design_only 93 | fn data_interop_design_only() { 94 | run_interop_tests(INTEROP_TESTS_PATH.join("design_only")); 95 | } 96 | 97 | #[test] 98 | /// #TST-read-artifact.basic 99 | fn data_interop_basic() { 100 | run_interop_tests(INTEROP_TESTS_PATH.join("basic")); 101 | } 102 | 103 | #[test] 104 | fn data_interop_settings() { 105 | run_interop_tests(INTEROP_TESTS_PATH.join("settings")); 106 | } 107 | 108 | #[test] 109 | /// #TST-read-artifact.lints 110 | fn data_interop_lints_error1() { 111 | run_interop_tests(INTEROP_TESTS_PATH.join("lints")); 112 | } 113 | 114 | #[test] 115 | fn data_interop_lints_error2() { 116 | run_interop_tests(INTEROP_TESTS_PATH.join("lints2")); 117 | } 118 | -------------------------------------------------------------------------------- /artifact-app/tests/lib_ser.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! FIXME: Test serialization/deserialization of `*Ser` Types 18 | -------------------------------------------------------------------------------- /artifact-data/.art/settings.toml: -------------------------------------------------------------------------------- 1 | # artifact project settings 2 | 3 | # Note: {cwd} == current directory of THIS file 4 | # {repo} == directory of the `.art` file 5 | 6 | # directories containing artifact toml files 7 | artifact_paths = ["{repo}/design"] 8 | 9 | # artifact paths to exclude. This is how you can avoid trying 10 | # to load .git/.hg/etc directories (or anything else you don't 11 | # want to include 12 | exclude_artifact_paths = [] 13 | 14 | # directories containing code that has artifact links 15 | code_paths = ["{repo}/src"] 16 | 17 | # directories to exclude when searching through code 18 | exclude_code_paths = [] 19 | 20 | file_type = "markdown" 21 | -------------------------------------------------------------------------------- /artifact-data/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | notes.md 3 | -------------------------------------------------------------------------------- /artifact-data/.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | # - stable 4 | # - beta 5 | - nightly 6 | matrix: 7 | allow_failures: 8 | - rust: nightly 9 | -------------------------------------------------------------------------------- /artifact-data/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Garrett Berg "] 3 | name = "artifact_data" 4 | version = "0.1.0" 5 | edition = "2018" 6 | 7 | [dependencies] 8 | base64 = "0.9.2" 9 | ergo = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 10 | expect_macro = "0.2.1" 11 | matches = "0.1.6" 12 | petgraph = "0.4.12" 13 | rayon = "1.0.1" 14 | serde = "1.0.66" 15 | serde_derive = "1.0.66" 16 | siphasher = "0.2.2" 17 | time = "0.1.40" 18 | failure = "0.1.1" 19 | failure_derive = "0.1.1" 20 | log = "0.4.2" 21 | artifact_lib = {path="../artifact-lib"} 22 | artifact_ser = {path="../artifact-ser"} 23 | 24 | [dev-dependencies] 25 | pretty_assertions = "0.5.1" 26 | proptest = "0.7.1" 27 | regex_generate = "0.2.0" 28 | tempdir = "0.3.7" 29 | unicode-segmentation = "1.2.1" 30 | 31 | [features] 32 | default = [] 33 | -------------------------------------------------------------------------------- /artifact-data/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Garrett Berg, vitiral@gmail.com 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /artifact-data/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Garrett Berg, vitiral@gmail.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /artifact-data/src/intermediate.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | use base64; 18 | use ergo::serde::{self, Deserialize, Deserializer, Serialize, Serializer}; 19 | use siphasher::sip128::{Hasher128, SipHasher}; 20 | use std::fmt; 21 | 22 | use crate::dev_prelude::*; 23 | use crate::raw::{self, ArtifactRaw, TextRaw}; 24 | use crate::raw_names::NamesRaw; 25 | 26 | pub trait ArtifactImExt { 27 | /// Get an `ArtifactIm` from an `ArtifactRaw`. 28 | fn from_raw(name: Name, file: PathFile, raw: ArtifactRaw) -> ArtifactIm; 29 | 30 | fn into_raw(self) -> (PathSer, Name, ArtifactRaw); 31 | } 32 | 33 | impl ArtifactImExt for ArtifactIm { 34 | fn from_raw(name: Name, file: PathFile, raw: ArtifactRaw) -> ArtifactIm { 35 | let mut partof = raw 36 | .partof 37 | .map(|mut p| { 38 | strip_auto_partofs(&name, &mut p.0); 39 | p.drain(..).collect() 40 | }) 41 | .unwrap_or_else(IndexSet::new); 42 | partof.sort(); 43 | 44 | ArtifactIm { 45 | name: name, 46 | file: file.into(), 47 | partof: partof, 48 | done: raw.done, 49 | text: raw.text.map(|t| t.0).unwrap_or_else(String::new), 50 | } 51 | } 52 | 53 | fn into_raw(self) -> (PathSer, Name, ArtifactRaw) { 54 | let partof = if self.partof.is_empty() { 55 | None 56 | } else { 57 | Some(NamesRaw::from(self.partof)) 58 | }; 59 | 60 | let text = if self.text.is_empty() { 61 | None 62 | } else { 63 | Some(TextRaw(self.text)) 64 | }; 65 | 66 | let raw = ArtifactRaw { 67 | done: self.done, 68 | partof: partof, 69 | text: text, 70 | }; 71 | (self.file, self.name, raw) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /artifact-data/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! The artifact data crate defines the method of serializing 18 | //! and deserializing raw artifact and processing them into 19 | //! a full project. 20 | //! 21 | //! Note that almost all tests for artifact-data are in artifact-test 22 | 23 | #![allow(dead_code)] 24 | #![allow(unused_imports)] 25 | #![allow(unknown_lints)] 26 | #![allow(clippy::doc_markdown)] 27 | 28 | #[macro_use] 29 | extern crate expect_macro; 30 | use failure; 31 | #[macro_use] 32 | extern crate matches; 33 | use petgraph; 34 | use rayon; 35 | 36 | #[macro_use] 37 | extern crate serde_derive; 38 | 39 | #[macro_use] 40 | extern crate failure_derive; 41 | use time; 42 | 43 | #[macro_use] 44 | extern crate artifact_lib; 45 | 46 | #[macro_use] 47 | extern crate log; 48 | 49 | // MODULES 50 | 51 | pub mod artifact; 52 | mod dev_prelude; 53 | pub mod graph; 54 | pub mod implemented; 55 | mod intermediate; 56 | mod modify; 57 | mod project; 58 | pub mod raw; 59 | #[macro_use] 60 | pub mod raw_names; 61 | mod settings; 62 | 63 | #[cfg(test)] 64 | #[macro_use] 65 | extern crate proptest; 66 | 67 | #[cfg(test)] 68 | #[macro_use] 69 | extern crate pretty_assertions; 70 | 71 | // #[cfg(test)] 72 | // extern crate rand; 73 | 74 | pub use crate::modify::modify_project; 75 | pub use crate::project::read_project; 76 | pub use crate::settings::{ART_DIR, SETTINGS_FILE}; 77 | -------------------------------------------------------------------------------- /artifact-data/src/raw_names.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! Define the serialization rules for raw names 18 | 19 | use crate::dev_prelude::*; 20 | use ergo::serde; 21 | use ergo::serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; 22 | use ergo::serde::ser::{Serialize, Serializer}; 23 | use std::fmt; 24 | 25 | #[macro_export] 26 | /// Macro to get 'raw' names with no error checking 27 | macro_rules! names_raw { 28 | ($raw:expr) => { 29 | match NamesRaw::from_str(&$raw) { 30 | Ok(n) => n, 31 | Err(e) => panic!("invalid names!({}): {}", $raw, e), 32 | } 33 | }; 34 | } 35 | 36 | /// Collection of `NamesRaw`. 37 | /// 38 | /// This mostly exists to provide custom 39 | /// serialization/deserializtion for a better text user interface. 40 | #[derive(Clone, Default, Eq, PartialEq)] 41 | pub struct NamesRaw(pub(crate) IndexSet); 42 | 43 | impl fmt::Debug for NamesRaw { 44 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 45 | write!(f, "{:?}", self.0) 46 | } 47 | } 48 | 49 | impl Deref for NamesRaw { 50 | type Target = IndexSet; 51 | 52 | fn deref(&self) -> &IndexSet { 53 | &self.0 54 | } 55 | } 56 | 57 | impl DerefMut for NamesRaw { 58 | fn deref_mut(&mut self) -> &mut IndexSet { 59 | &mut self.0 60 | } 61 | } 62 | 63 | impl From> for NamesRaw { 64 | fn from(names: IndexSet) -> NamesRaw { 65 | NamesRaw(names) 66 | } 67 | } 68 | 69 | impl From> for NamesRaw { 70 | fn from(mut names: HashSet) -> NamesRaw { 71 | NamesRaw(names.drain().collect()) 72 | } 73 | } 74 | 75 | impl FromStr for NamesRaw { 76 | type Err = Error; 77 | /// Parse a collapsed set of names to create them 78 | fn from_str(collapsed: &str) -> Result { 79 | Ok(NamesRaw(expand_names(collapsed)?)) 80 | } 81 | } 82 | 83 | impl Serialize for NamesRaw { 84 | fn serialize(&self, serializer: S) -> result::Result 85 | where 86 | S: Serializer, 87 | { 88 | if self.0.is_empty() { 89 | panic!("attempted to serialize an empty names field"); 90 | } else if self.0.len() == 1 { 91 | // serialize just the string 92 | expect!(self.0.iter().next()).serialize(serializer) 93 | } else { 94 | // serialize the sorted names 95 | let mut names: Vec<_> = self.0.iter().collect(); 96 | names.sort(); 97 | names.serialize(serializer) 98 | } 99 | } 100 | } 101 | 102 | impl<'de> Deserialize<'de> for NamesRaw { 103 | fn deserialize(deserializer: D) -> result::Result 104 | where 105 | D: Deserializer<'de>, 106 | { 107 | deserializer.deserialize_any(NamesRawVisitor) 108 | } 109 | } 110 | 111 | struct NamesRawVisitor; 112 | 113 | impl<'de> Visitor<'de> for NamesRawVisitor { 114 | type Value = NamesRaw; 115 | 116 | fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 117 | formatter.write_str("an artifact or list of artifacts that can be in collapsed form") 118 | } 119 | 120 | fn visit_str(self, v: &str) -> result::Result 121 | where 122 | E: serde::de::Error, 123 | { 124 | NamesRaw::from_str(v).map_err(serde::de::Error::custom) 125 | } 126 | 127 | fn visit_seq(self, mut seq: A) -> result::Result 128 | where 129 | A: SeqAccess<'de>, 130 | { 131 | let mut out = NamesRaw::default(); 132 | // Note: `::` is necessary 133 | while let Some(s) = seq.next_element::()? { 134 | let mut elem = NamesRaw::from_str(&s).map_err(serde::de::Error::custom)?; 135 | out.extend(elem.drain(..)); 136 | } 137 | Ok(out) 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /artifact-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | notes.md 3 | -------------------------------------------------------------------------------- /artifact-frontend/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "artifact-frontend" 3 | version = "0.1.0" 4 | authors = ["Garrett Berg "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | yew = "0.4.0" 9 | stdweb = "0.4.13" 10 | artifact_ser = {path="../artifact-ser"} 11 | ergo_std = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 12 | ergo_config = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 13 | yew_simple = "0.3.0" 14 | expect_macro = "0.2.1" 15 | jrpc = "0.4.0" 16 | http = "0.1.14" 17 | 18 | [dev-dependencies] 19 | -------------------------------------------------------------------------------- /artifact-frontend/shell.nix: -------------------------------------------------------------------------------- 1 | 2 | with import {}; 3 | 4 | stdenv.mkDerivation { 5 | name = "rust-env"; 6 | buildInputs = [ 7 | rustc cargo 8 | 9 | # dependencies 10 | graphviz 11 | emscripten 12 | ]; 13 | 14 | RUST_BACKTRACE=1; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /artifact-frontend/src/example.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | pub const YAML: &str = r###" 18 | settings: 19 | base: "/fake" 20 | code_paths: [] 21 | exclude_code_paths: [] 22 | 23 | artifact_paths: 24 | - /fake/design 25 | exclude_artifact_paths: [] 26 | 27 | settings_path: "/fake/.art/settings.toml" 28 | 29 | code_impls: {} 30 | 31 | artifacts: 32 | REQ-purpose: 33 | id: "gQ7cdQ7bvyIoaUTEUsxMsg" 34 | name: REQ-purpose 35 | file: /fake/design/purpose.md 36 | partof: [] 37 | parts: [] 38 | completed: {spc: 0.0, tst: 0.0} 39 | text: This text was updated 40 | impl_: 41 | type: NotImpl 42 | value: null 43 | subnames: [] 44 | REQ-single: 45 | id: "gp7cdQ7bvyIoaUTEUsxMsg" 46 | name: REQ-single 47 | file: /fake/design/purpose.md 48 | partof: [] 49 | parts: [] 50 | completed: {spc: 0.0, tst: 0.0} 51 | text: |- # note `|-` => strip newline at the end 52 | This is a single line of text 53 | impl_: 54 | type: NotImpl 55 | value: null 56 | subnames: [] 57 | REQ-completed: 58 | id: "gp9cdQ7bvyIoaUTEUsxMsg" 59 | name: REQ-completed 60 | file: /fake/design/purpose.md 61 | partof: [] 62 | parts: 63 | - SPC-completed 64 | - SPC-wut 65 | completed: {spc: 0.25, tst: 1.0} 66 | text: | 67 | Basic demonstration of completeness 68 | 69 | Has some subnames: 70 | - [[.one]] 71 | - [[.two]] 72 | impl_: 73 | type: NotImpl 74 | value: null 75 | subnames: 76 | - .one 77 | - .two 78 | SPC-completed: 79 | id: "gp9ckQ7bvyIoaUTEUsxMsg" 80 | name: SPC-completed 81 | file: /fake/design/purpose.md 82 | partof: 83 | - REQ-completed 84 | parts: [] 85 | completed: {spc: 1.0, tst: 1.0} 86 | text: |- 87 | Just marked as done 88 | impl_: 89 | type: Done 90 | value: "this is done" 91 | subnames: [] 92 | SPC-wut: 93 | id: "gp9ckQ7bvyzoaUTEUsxMsg" 94 | name: SPC-wut 95 | file: /fake/design/purpose.md 96 | partof: 97 | - REQ-completed 98 | parts: [] 99 | completed: {spc: 1.0, tst: 1.0} 100 | text: |- 101 | Just marked as done 102 | impl_: 103 | type: Done 104 | value: "this is done" 105 | subnames: [] 106 | "###; 107 | -------------------------------------------------------------------------------- /artifact-frontend/src/graph.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | 18 | use artifact_ser::md_graph; 19 | use stdweb::web::Node; 20 | use yew::virtual_dom::VNode; 21 | 22 | use crate::dev_prelude::*; 23 | use crate::view::ser_markdown; 24 | 25 | /// The small graph at the top of every artifact, displaying it's `partof` and `parts`. 26 | pub(crate) fn artifact_part_html(model: &Model, art: &ArtifactSer) -> HtmlApp { 27 | let md = ser_markdown(model); 28 | let dot = md_graph::artifact_part_dot(&md, art); 29 | dot_html(&dot) 30 | } 31 | 32 | pub(crate) fn graph_html(model: &Model) -> ViewResult { 33 | let page = html![ 34 |
35 | { graph_html_results(model) } 36 |
37 | ]; 38 | 39 | let nav_extra = Some(html![ 40 | 41 | { "Filter:" } 42 | 48 | 49 | 50 | ]); 51 | 52 | ViewResult { page, nav_extra } 53 | } 54 | 55 | /// Get the dot html for untrusted dot. 56 | pub(crate) fn dot_html_string(dot: &str) -> String { 57 | let html = js! { 58 | try { 59 | var svg = Viz(@{dot}); 60 | return svg; 61 | } catch ( error ) { 62 | return ( 63 | "

ERROR: Invalid SVG

\n" + error.message 64 | + "\n
" + @{dot} + "\n
\n" 65 | ); 66 | } 67 | }; 68 | expect!(html.into_string()) 69 | } 70 | 71 | /// Convert DOT to HTML 72 | pub(crate) fn dot_html(dot: &str) -> HtmlApp { 73 | let dot_string = dot_html_string(dot); 74 | let dot_string = format!("
{}
", dot_string); 75 | let node = expect!(Node::from_html(&dot_string), "invalid html"); 76 | let svg = VNode::VRef(node); 77 | html![ 78 |
79 | { svg } 80 |
81 | ] 82 | } 83 | 84 | /// The "search graph". 85 | fn graph_html_results(model: &Model) -> HtmlApp { 86 | let md = ser_markdown(model); 87 | 88 | let re = match parse_regex(&model.graph.search) { 89 | Ok(r) => r, 90 | Err(e) => return e, 91 | }; 92 | let mut dot = String::new(); 93 | 94 | let focus: HashMap<&Name, &ArtifactSer> = model 95 | .shared 96 | .artifacts 97 | .iter() 98 | .filter(|(n, _)| re.is_match(n.as_str())) 99 | .collect(); 100 | 101 | for (name, art) in &focus { 102 | dot.push_str(&md_graph::name_dot(&md, name, true)); 103 | 104 | // push the parts+partof, but only if they are not also 105 | // in focus (if they are in focus they will be pushed 106 | // separately) 107 | for part in &art.parts { 108 | if !focus.contains_key(part) { 109 | dot.push_str(&md_graph::name_dot(&md, part, false)); 110 | } 111 | } 112 | 113 | for part in &art.partof { 114 | if !focus.contains_key(part) { 115 | dot.push_str(&md_graph::name_dot(&md, part, false)); 116 | } 117 | } 118 | } 119 | 120 | let mut connections: HashSet<(&Name, &Name)> = HashSet::new(); 121 | 122 | for (name, art) in &focus { 123 | for part in &art.parts { 124 | connections.insert((name, part)); 125 | } 126 | for part in &art.partof { 127 | connections.insert((part, name)); 128 | } 129 | } 130 | 131 | for (from, to) in connections { 132 | dot.push_str(&md_graph::connect_names_dot(from, to)); 133 | } 134 | 135 | dot_html(&md_graph::wrap_dot(&dot, false)) 136 | } 137 | -------------------------------------------------------------------------------- /artifact-frontend/src/name.rs: -------------------------------------------------------------------------------- 1 | use crate::dev_prelude::*; 2 | 3 | pub(crate) fn name_html(model: &Model, name: &Name) -> HtmlApp { 4 | let color = match model.shared.artifacts.get(name) { 5 | Some(art) => art.completed.name_color(), 6 | None => GRAY, 7 | }; 8 | 9 | html![
] 12 | } 13 | -------------------------------------------------------------------------------- /artifact-frontend/src/view.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | use yew_simple; 18 | 19 | use crate::dev_prelude::*; 20 | use crate::graph; 21 | use artifact_ser; 22 | 23 | lazy_static! { 24 | static ref NAME_URL: Regex = expect!(Regex::new(&format!( 25 | r"(?i)(?:artifacts/)?({})", 26 | NAME_VALID_STR 27 | ))); 28 | static ref EDIT_URL: Regex = expect!(Regex::new(r"(?i)edit/(\d+)")); 29 | static ref REPLACE_TEXT_RE: Regex = expect!(Regex::new( 30 | r#"(?xim) 31 | (?:^```dot\s*\n(?P[\s\S]+?\n)```$) # graphviz dot rendering 32 | "#, 33 | )); 34 | } 35 | 36 | /// The function used for routing urls. 37 | #[allow(clippy::needless_pass_by_value)] 38 | pub(crate) fn router_fn(info: yew_simple::RouteInfo) -> Msg { 39 | let hash = info.url.fragment().unwrap_or_default(); 40 | let view = View::from_hash(hash); 41 | Msg::SetView(view) 42 | } 43 | 44 | impl View { 45 | pub(crate) fn from_hash(hash: &str) -> View { 46 | if hash.to_ascii_lowercase() == "graph" || hash == "" { 47 | View::Graph 48 | } else if let Some(cap) = NAME_URL.captures(hash) { 49 | let name = name!(&cap[1]); 50 | View::Artifact(name) 51 | } else if let Some(cap) = EDIT_URL.captures(hash) { 52 | let id = match usize::from_str(&cap[1]) { 53 | Ok(id) => id, 54 | Err(_) => return View::NotFound, 55 | }; 56 | View::Edit(id) 57 | } else { 58 | View::NotFound 59 | } 60 | } 61 | } 62 | 63 | /// Render the markdown correctly. 64 | /// 65 | /// `parent` is the parent's name, which may or may not exist/be-valid. 66 | pub(crate) fn markdown_html(model: &Model, parent: &str, markdown: &str) -> HtmlApp { 67 | let md = ser_markdown(model); 68 | let markdown = md.replace_markdown(parent, markdown); 69 | let markdown = replace_markdown(&markdown).to_string(); 70 | let value = js! { 71 | var reader = new commonmark.Parser(); 72 | var writer = new commonmark.HtmlRenderer(); 73 | var parsed = reader.parse(@{markdown}); 74 | return writer.render(parsed); 75 | }; 76 | 77 | let mut md_html = expect!(value.into_string(), "markdown not a string"); 78 | md_html.insert_str(0, "
"); 79 | md_html.push_str("
"); 80 | let node = expect!(Node::from_html(md_html.trim()), "md-html: {}", md_html); 81 | VNode::VRef(node) 82 | } 83 | 84 | /// Return the default SerMarkdown object for the frontend. 85 | pub(crate) fn ser_markdown(model: &Model) -> artifact_ser::markdown::SerMarkdown<'_> { 86 | use artifact_ser::markdown::*; 87 | let settings = SerMarkdownSettings { 88 | code_url: model.shared.settings.code_url.clone(), 89 | family: SettingsMdFamily::Dot, 90 | dot: SettingsMdDot::Ignore, 91 | name_prefix: "".to_string(), 92 | // md_plain: false, 93 | // md_details: SettingsMdDetails::default(), 94 | }; 95 | 96 | SerMarkdown::with_settings(&model.shared, settings) 97 | } 98 | 99 | fn replace_markdown<'t>(markdown: &'t str) -> Cow<'t, str> { 100 | let replacer = |cap: &::ergo_std::regex::Captures<'_>| -> String { 101 | if let Some(dot) = cap.name("dot") { 102 | replace_markdown_dot(dot.as_str()) 103 | } else { 104 | panic!("Got unknown match in md: {:?}", cap); 105 | } 106 | }; 107 | REPLACE_TEXT_RE.replace_all(markdown, replacer) 108 | } 109 | 110 | fn replace_markdown_dot(dot: &str) -> String { 111 | let html = graph::dot_html_string(dot); 112 | format!("\n\n{0}\n\n", html) 113 | } 114 | -------------------------------------------------------------------------------- /artifact-frontend/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Artifacts 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /artifact-frontend/static/initial.json: -------------------------------------------------------------------------------- 1 | { 2 | "project": null, 3 | "web_type": "Static" 4 | } 5 | -------------------------------------------------------------------------------- /artifact-lib/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /artifact-lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "artifact_lib" 3 | version = "0.1.0" 4 | authors = ["Garrett Berg "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | base64 = "0.9.2" 9 | path_abs = {git="https://github.com/vitiral/path_abs"} 10 | serde = "1.0.66" 11 | serde_derive = "1.0.66" 12 | failure = "0.1.1" 13 | failure_derive = "0.1.1" 14 | expect_macro = "0.2.1" 15 | ergo_std = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 16 | ergo_config = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 17 | siphasher = "0.2.2" 18 | artifact_ser = { path = "../artifact-ser" } 19 | -------------------------------------------------------------------------------- /artifact-lib/src/dev_prelude.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | pub use ergo_config::*; 18 | pub use ergo_std::*; 19 | pub use expect_macro::*; 20 | pub use failure::Error; 21 | pub use failure::*; 22 | pub use path_abs::*; 23 | pub use std::result; 24 | -------------------------------------------------------------------------------- /artifact-ser/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /artifact-ser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "artifact_ser" 3 | version = "0.1.0" 4 | authors = ["Garrett Berg "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | serde = "1.0.66" 9 | serde_derive = "1.0.66" 10 | expect_macro = "0.2.1" 11 | lazy_static = "1.0.1" 12 | indexmap = "1.0.1" 13 | ergo_std = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 14 | ergo_config = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 15 | base64 = "0.9.2" 16 | derive-error = "0.0.4" 17 | strfmt = "0.1.6" 18 | -------------------------------------------------------------------------------- /artifact-ser/src/dev_prelude.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | 18 | pub use ergo_config::*; 19 | pub use ergo_std::*; 20 | -------------------------------------------------------------------------------- /artifact-ser/src/expand_names.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! Module for defining logic for parsing collapsed artifact names and 18 | //! recollapsing them for tests 19 | //! 20 | //! This feature was added before artifact 1.0 and was purposely preserved. 21 | //! It is *definitely* a "poweruser" feature, but it can come in handy. 22 | //! 23 | //! However, the implementation is not ideal. In particular I would like 24 | //! to use a legitamite parsing library instead of the hand crafted 25 | //! regression parsing seen here. However, I do believe this works. 26 | //! 27 | //! Notes: this is tested in `test_family.rs` 28 | 29 | use crate::dev_prelude::*; 30 | use crate::name::{Name, NameError}; 31 | 32 | /// Expand a string of names into multiple names. 33 | /// 34 | /// i.e. `"REQ-[foo, bar]"` -> `["REQ-foo", "REQ-bar"]` 35 | pub fn expand_names(raw: &str) -> Result, NameError> { 36 | parse_collapsed(&mut raw.chars(), false)? 37 | .iter() 38 | .map(|n| Name::from_str(n)) 39 | .collect() 40 | } 41 | 42 | // Private: Expanding Names. Use `Name::from_str` 43 | 44 | /// subfunction to parse names from a names-str recusively 45 | fn parse_collapsed(raw: &mut I, in_brackets: bool) -> Result, NameError> 46 | where 47 | I: Iterator, 48 | { 49 | // hello-[there, you-[are, great]] 50 | // hello-there, hello-you-are, hello-you-great 51 | let mut strout = String::new(); 52 | let mut current = String::new(); 53 | loop { 54 | let c = match raw.next() { 55 | Some(c) => c, 56 | None => { 57 | if in_brackets { 58 | return Err(NameError::InvalidCollapsed { 59 | msg: "brackets are not closed".into(), 60 | } 61 | .into()); 62 | } 63 | break; 64 | } 65 | }; 66 | match c { 67 | ' ' | '\n' | '\r' => {} 68 | // ignore whitespace 69 | '[' => { 70 | if current == "" { 71 | // SPC-names.2: more validation 72 | let msg = "cannot have '[' after characters ',' or ']'\ 73 | or at start of string"; 74 | return Err(NameError::InvalidCollapsed { msg: msg.into() }.into()); 75 | } 76 | for p in r#try!(parse_collapsed(raw, true)) { 77 | strout.push_str(¤t); 78 | strout.push_str(&p); 79 | strout.push(','); 80 | } 81 | current.clear(); 82 | } 83 | ']' => { 84 | if !in_brackets { 85 | let err = NameError::InvalidCollapsed { 86 | msg: "`]` character wasn't opened".into(), 87 | }; 88 | return Err(err.into()); 89 | } else { 90 | break; 91 | } 92 | } 93 | ',' => { 94 | strout.write_str(¤t).unwrap(); 95 | strout.push(','); 96 | current.clear(); 97 | } 98 | _ => current.push(c), 99 | } 100 | } 101 | strout.write_str(¤t).unwrap(); 102 | Ok(strout 103 | .split(',') 104 | .filter(|s| s != &"") 105 | .map(|s| s.to_string()) 106 | .collect()) 107 | } 108 | -------------------------------------------------------------------------------- /artifact-test/.gitignore: -------------------------------------------------------------------------------- 1 | /_gh-pages 2 | # Generated by Cargo 3 | # will have compiled files and executables 4 | /target/ 5 | /target-install/ 6 | .cache 7 | *.log 8 | node_modules 9 | *.ropeproject 10 | result 11 | -------------------------------------------------------------------------------- /artifact-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "artifact_test" 3 | version = "0.1.0" 4 | authors = ["Garrett Berg "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | artifact_data = { path = "../artifact-data" } 9 | artifact_lib = { path = "../artifact-lib" } 10 | pretty_assertions = "0.5.1" 11 | proptest = "0.7.1" 12 | regex_generate = "0.2.0" 13 | tempdir = "0.3.7" 14 | unicode-segmentation = "1.2.1" 15 | 16 | base64 = "0.9.2" 17 | ergo = {git="https://github.com/rust-crates/ergo", branch="path_abs-4.0"} 18 | expect_macro = "0.2.1" 19 | matches = "0.1.6" 20 | petgraph = "0.4.12" 21 | rayon = "1.0.1" 22 | serde = "1.0.66" 23 | serde_derive = "1.0.66" 24 | siphasher = "0.2.2" 25 | time = "0.1.40" 26 | failure = "0.1.1" 27 | failure_derive = "0.1.1" 28 | log = "0.4.2" 29 | -------------------------------------------------------------------------------- /artifact-test/README.md: -------------------------------------------------------------------------------- 1 | # Testing framework and Property Based Testing 2 | 3 | This subcrate is to provide a common testing framework/functions 4 | for testing artifact. 5 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/.art/settings.toml: -------------------------------------------------------------------------------- 1 | # artifact project settings 2 | 3 | # Note: {cwd} == current directory of THIS file 4 | # {repo} == directory of the `.art` file 5 | 6 | # directories containing artifact toml files 7 | artifact_paths = ["{repo}/design"] 8 | 9 | # artifact paths to exclude. This is how you can avoid trying 10 | # to load .git/.hg/etc directories (or anything else you don't 11 | # want to include 12 | exclude_artifact_paths = [] 13 | 14 | # directories containing code that has artifact links 15 | code_paths = ["/src", "/build.rs"] 16 | 17 | # directories to exclude when searching through code 18 | exclude_code_paths = [] 19 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "basic" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "basic" 3 | version = "0.1.0" 4 | authors = ["Garrett Berg "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/assert-cases/basic/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | # no lints 2 | error: [] 3 | other: [] 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/assert-cases/basic/assert_project_lints.yaml: -------------------------------------------------------------------------------- 1 | error: [] 2 | other: [] 3 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/build.rs: -------------------------------------------------------------------------------- 1 | //! #SPC-build 2 | //! 3 | //! Build file, included by direct path 4 | 5 | // And some test: #TST-build (but not subpart) 6 | // Also a unit test: #SPC-build.tst-unit 7 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/design/foo.md: -------------------------------------------------------------------------------- 1 | # SPC-foo 2 | This is the spec for foo, it does lots of foo. 3 | 4 | It is some foo subparts: 5 | - [[.no]]: not done 6 | - [[.yes]]: done 7 | 8 | 9 | # SPC-foo_done 10 | partof: 11 | - SPC-foo 12 | - REQ-foo 13 | 14 | done: this is done 15 | ### 16 | This is done and is weird? 17 | 18 | 19 | # TST-foo 20 | Partially done foo test with some subparts 21 | 22 | - [[.no1]] 23 | - [[.no2]] 24 | - [[.yes1]] 25 | - [[.yes2]] 26 | - [[.yes3]] 27 | - [[.yes4]] 28 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/design/purpose.md: -------------------------------------------------------------------------------- 1 | # REQ-purpose 2 | The purpose of this project is is to test a basic 3 | project... that's it! 4 | 5 | # REQ-lib 6 | partof: REQ-purpose 7 | ### 8 | Lib is definitely a library 9 | 10 | 11 | # REQ-foo 12 | partof: REQ-purpose 13 | ### 14 | foo needs to do the foo thing 15 | 16 | # REQ-baz 17 | implemented directly in source! 18 | 19 | Not a partof anything... 20 | 21 | # SPC-build 22 | partof: REQ-purpose 23 | ### 24 | This has a build file. 25 | 26 | Unit tests: 27 | - [[.tst-unit]] 28 | 29 | # TST-build 30 | partof: REQ-purpose 31 | ### 32 | direct link to REQ-purpose 33 | 34 | - [[.no]] 35 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/src/baz.rs: -------------------------------------------------------------------------------- 1 | /// #REQ-baz 2 | /// Just implement baz directly 3 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/src/foo/fab.rs: -------------------------------------------------------------------------------- 1 | //! This has foo stuff 2 | 3 | 4 | /// #SPC-foo.yes 5 | /// Do foo? 6 | fn foo() { 7 | } 8 | 9 | #[test] 10 | /// #TST-foo.yes4 11 | fn test_samefile() { 12 | println!("TST-foo"); // nothing happens without `#` 13 | } 14 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/src/foo/mod.rs: -------------------------------------------------------------------------------- 1 | /// #SPC-foo 2 | /// 3 | /// This is where foo is implemented 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/src/foo/test.rs: -------------------------------------------------------------------------------- 1 | /// Test foo and stuff. Don't link TST-foo directly 2 | 3 | 4 | #[test] 5 | /// #TST-foo.yes1 6 | fn foo_1() { 7 | // #TST-foo.yes2 8 | // #TST-foo.yes3 9 | } 10 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/basic/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/.art/settings.toml: -------------------------------------------------------------------------------- 1 | # artifact project settings 2 | 3 | # Note: {cwd} == current directory of THIS file 4 | # {repo} == directory of the `.art` file 5 | 6 | # directories containing artifact toml files 7 | artifact_paths = ["{repo}/design"] 8 | 9 | # artifact paths to exclude. This is how you can avoid trying 10 | # to load .git/.hg/etc directories (or anything else you don't 11 | # want to include 12 | exclude_artifact_paths = [] 13 | 14 | # directories containing code that has artifact links 15 | code_paths = [] 16 | 17 | # directories to exclude when searching through code 18 | exclude_code_paths = [] 19 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/basic/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | # no lints 2 | error: [] 3 | other: [] 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/basic/assert_project.yaml: -------------------------------------------------------------------------------- 1 | # Empty project 2 | # 3 | # This file is also used as a template 4 | settings: 5 | code_paths: [] 6 | exclude_code_paths: [] 7 | 8 | artifact_paths: 9 | - design 10 | exclude_artifact_paths: [] 11 | 12 | code_impls: {} 13 | 14 | artifacts: 15 | REQ-purpose: 16 | name: REQ-purpose 17 | file: design/purpose.md 18 | partof: [] 19 | parts: [] 20 | completed: {spc: 0.0, tst: 0.0} 21 | text: | # note `|` => multiline string 22 | The purpose of this project is to test loading artifact designs. 23 | 24 | This is on a new line. 25 | impl_: null 26 | subnames: [] 27 | REQ-single: 28 | name: REQ-single 29 | file: design/purpose.md 30 | partof: [] 31 | parts: [] 32 | completed: {spc: 0.0, tst: 0.0} 33 | text: |- # note `|-` => strip newline at the end 34 | This is a single line of text 35 | impl_: null 36 | subnames: [] 37 | REQ-completed: 38 | name: REQ-completed 39 | file: design/purpose.md 40 | partof: [] 41 | parts: 42 | - SPC-completed 43 | completed: {spc: 0.25, tst: 1.0} 44 | text: | 45 | Basic demonstration of completeness 46 | 47 | Has some subnames: 48 | - [[.one]] 49 | - [[.two]] 50 | impl_: null 51 | subnames: 52 | - .one 53 | - .two 54 | SPC-completed: 55 | name: SPC-completed 56 | file: design/purpose.md 57 | partof: 58 | - REQ-completed 59 | parts: [] 60 | completed: {spc: 1.0, tst: 1.0} 61 | text: |- 62 | Just marked as done 63 | impl_: "this is done" 64 | subnames: [] 65 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/delete/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | # no lints 2 | error: [] 3 | other: [] 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/delete/assert_project.yaml: -------------------------------------------------------------------------------- 1 | # Empty project 2 | # 3 | # This file is also used as a template 4 | settings: 5 | code_paths: [] 6 | exclude_code_paths: [] 7 | 8 | artifact_paths: 9 | - design 10 | exclude_artifact_paths: [] 11 | 12 | code_impls: {} 13 | 14 | artifacts: 15 | REQ-single: 16 | name: REQ-single 17 | file: design/purpose.md 18 | partof: [] 19 | parts: [] 20 | completed: {spc: 0.0, tst: 0.0} 21 | text: |- # note `|-` => strip newline at the end 22 | This is a single line of text 23 | impl_: null 24 | subnames: [] 25 | REQ-completed: 26 | name: REQ-completed 27 | file: design/purpose.md 28 | partof: [] 29 | parts: 30 | - SPC-completed 31 | completed: {spc: 0.25, tst: 1.0} 32 | text: | 33 | Basic demonstration of completeness 34 | 35 | Has some subnames: 36 | - [[.one]] 37 | - [[.two]] 38 | impl_: null 39 | subnames: 40 | - .one 41 | - .two 42 | SPC-completed: 43 | name: SPC-completed 44 | file: design/purpose.md 45 | partof: 46 | - REQ-completed 47 | parts: [] 48 | completed: {spc: 1.0, tst: 1.0} 49 | text: |- 50 | Just marked as done 51 | impl_: "this is done" 52 | subnames: [] 53 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/delete/modify.yaml: -------------------------------------------------------------------------------- 1 | - 2 | op: delete 3 | name: REQ-purpose 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/multi/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | # no lints 2 | error: [] 3 | other: [] 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/multi/assert_project.yaml: -------------------------------------------------------------------------------- 1 | # Empty project 2 | # 3 | # This file is also used as a template 4 | settings: 5 | code_paths: [] 6 | exclude_code_paths: [] 7 | 8 | artifact_paths: 9 | - design 10 | exclude_artifact_paths: [] 11 | 12 | code_impls: {} 13 | 14 | artifacts: 15 | REQ-purpose: 16 | name: REQ-purpose 17 | file: design/purpose.md 18 | partof: [] 19 | parts: [REQ-new] 20 | completed: {spc: 0.0, tst: 0.0} 21 | text: | 22 | The purpose of this project is to test loading artifact designs. 23 | 24 | This is on a new line. 25 | impl_: null 26 | subnames: [] 27 | REQ-new: 28 | name: REQ-new 29 | file: design/new.md 30 | partof: 31 | - REQ-purpose 32 | parts: [] 33 | completed: {spc: 0.0, tst: 0.0} 34 | text: |- 35 | This was created out of whole cloth 36 | impl_: null 37 | subnames: [] 38 | REQ-completed: 39 | name: REQ-completed 40 | file: design/purpose.md 41 | partof: [] 42 | parts: 43 | - SPC-completed-changed 44 | completed: {spc: 0.25, tst: 1.0} 45 | text: | 46 | Basic demonstration of completeness 47 | 48 | Has some subnames: 49 | - [[.one]] 50 | - [[.two]] 51 | impl_: null 52 | subnames: 53 | - .one 54 | - .two 55 | SPC-completed-changed: 56 | name: SPC-completed-changed 57 | file: design/purpose.md 58 | partof: 59 | - REQ-completed 60 | parts: [] 61 | completed: {spc: 1.0, tst: 1.0} 62 | text: |- 63 | Still just marked as done. 64 | impl_: "still done" 65 | subnames: [] 66 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/multi/modify.yaml: -------------------------------------------------------------------------------- 1 | - 2 | op: update 3 | name: SPC-completed 4 | artifact: 5 | name: SPC-completed-changed 6 | file: design/purpose.md 7 | partof: 8 | - REQ-completed 9 | done: "still done" 10 | text: |- 11 | Still just marked as done. 12 | - 13 | op: delete 14 | name: REQ-single 15 | - 16 | op: create 17 | artifact: 18 | name: REQ-new 19 | file: design/new.md 20 | partof: 21 | - REQ-purpose 22 | done: null 23 | text: |- 24 | This was created out of whole cloth 25 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/overlap/assert_modify_fail.yaml: -------------------------------------------------------------------------------- 1 | error: 2 | - 3 | level: Error 4 | path: null 5 | line: null 6 | category: IdOverlap 7 | msg: "Attempting to operate twice on REQ-purpose" 8 | other: [] 9 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/overlap/modify.yaml: -------------------------------------------------------------------------------- 1 | - 2 | op: update 3 | name: REQ-purpose 4 | artifact: 5 | name: REQ-purpose 6 | file: design/purpose.md 7 | partof: [] 8 | done: null 9 | text: This text was updated 10 | - 11 | op: update 12 | name: REQ-purpose 13 | artifact: 14 | name: REQ-purpose 15 | file: design/purpose.md 16 | partof: [] 17 | done: null 18 | text: This text was updated 19 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/update-dne/assert_modify_fail.yaml: -------------------------------------------------------------------------------- 1 | error: 2 | - 3 | level: Error 4 | path: null 5 | line: null 6 | category: UpdateDne 7 | msg: "Attempt to update 'TST-dne' failed, hash-id does not exist" 8 | other: [] 9 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/update-dne/modify.yaml: -------------------------------------------------------------------------------- 1 | - 2 | op: update 3 | name: TST-dne 4 | artifact: 5 | name: TST-dne 6 | file: design/purpose.md 7 | partof: [] 8 | done: null 9 | text: This test does not exist 10 | 11 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/update-invalid-id/assert_modify_fail.yaml: -------------------------------------------------------------------------------- 1 | error: 2 | - 3 | level: Error 4 | path: null 5 | line: null 6 | category: UpdateDne 7 | msg: "Attempt to update 'REQ-purpose' failed, hash-id does not exist" 8 | other: [] 9 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/update-invalid-id/modify.yaml: -------------------------------------------------------------------------------- 1 | - 2 | op: update 3 | name: REQ-purpose 4 | artifact: 5 | name: REQ-purpose 6 | file: design/purpose.md 7 | partof: [] 8 | done: null 9 | text: "changing stuff, wrong id" 10 | id: "gQ7cdQ7IvyIoaUTEUsxMsg" 11 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/update/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | # no lints 2 | error: [] 3 | other: [] 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/update/assert_project.yaml: -------------------------------------------------------------------------------- 1 | # Empty project 2 | # 3 | # This file is also used as a template 4 | settings: 5 | code_paths: [] 6 | exclude_code_paths: [] 7 | 8 | artifact_paths: 9 | - design 10 | exclude_artifact_paths: [] 11 | 12 | code_impls: {} 13 | 14 | artifacts: 15 | REQ-purpose: 16 | name: REQ-purpose 17 | file: design/purpose.md 18 | partof: [] 19 | parts: [] 20 | completed: {spc: 0.0, tst: 0.0} 21 | text: This text was updated 22 | impl_: null 23 | subnames: [] 24 | REQ-single: 25 | name: REQ-single 26 | file: design/purpose.md 27 | partof: [] 28 | parts: [] 29 | completed: {spc: 0.0, tst: 0.0} 30 | text: |- # note `|-` => strip newline at the end 31 | This is a single line of text 32 | impl_: null 33 | subnames: [] 34 | REQ-completed: 35 | name: REQ-completed 36 | file: design/purpose.md 37 | partof: [] 38 | parts: 39 | - SPC-completed 40 | completed: {spc: 0.25, tst: 1.0} 41 | text: | 42 | Basic demonstration of completeness 43 | 44 | Has some subnames: 45 | - [[.one]] 46 | - [[.two]] 47 | impl_: null 48 | subnames: 49 | - .one 50 | - .two 51 | SPC-completed: 52 | name: SPC-completed 53 | file: design/purpose.md 54 | partof: 55 | - REQ-completed 56 | parts: [] 57 | completed: {spc: 1.0, tst: 1.0} 58 | text: |- 59 | Just marked as done 60 | impl_: "this is done" 61 | subnames: [] 62 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/assert-cases/update/modify.yaml: -------------------------------------------------------------------------------- 1 | - 2 | op: update 3 | name: REQ-purpose 4 | artifact: 5 | name: REQ-purpose 6 | file: design/purpose.md 7 | partof: [] 8 | done: null 9 | text: This text was updated 10 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/design_only/design/purpose.md: -------------------------------------------------------------------------------- 1 | # REQ-purpose 2 | The purpose of this project is to test loading artifact designs. 3 | 4 | This is on a new line. 5 | 6 | # REQ-single 7 | This is a single line of text 8 | 9 | # REQ-completed 10 | Basic demonstration of completeness 11 | 12 | Has some subnames: 13 | - [[.one]] 14 | - [[.two]] 15 | 16 | # SPC-completed 17 | done: this is done 18 | ### 19 | Just marked as done 20 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/empty/.art/settings.toml: -------------------------------------------------------------------------------- 1 | # artifact project settings 2 | 3 | # Note: {cwd} == current directory of THIS file 4 | # {repo} == directory of the `.art` file 5 | 6 | # directories containing artifact toml files 7 | artifact_paths = ["{repo}/design"] 8 | 9 | # artifact paths to exclude. This is how you can avoid trying 10 | # to load .git/.hg/etc directories (or anything else you don't 11 | # want to include 12 | exclude_artifact_paths = [] 13 | 14 | # directories containing code that has artifact links 15 | code_paths = [] 16 | 17 | # directories to exclude when searching through code 18 | exclude_code_paths = [] 19 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/empty/assert-cases/basic/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | # no lints 2 | error: [] 3 | other: [] 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/empty/assert-cases/basic/assert_project.yaml: -------------------------------------------------------------------------------- 1 | # Empty project 2 | # 3 | # This file is also used as a template 4 | settings: 5 | code_paths: [] 6 | exclude_code_paths: [] 7 | 8 | artifact_paths: [ 9 | "design", 10 | ] 11 | exclude_artifact_paths: [] 12 | 13 | code_impls: {} 14 | # TST-pyinit: 15 | # primary: 16 | # file: pylib/__init__.py 17 | # line: 0 18 | # secondary: {} 19 | 20 | artifacts: {} 21 | # REQ-purpose: 22 | # name: REQ-foo 23 | # file: design/purpose.md 24 | # partof: [] 25 | # parts: [] 26 | # completed: {spc: 0.0, tst: 0.0} 27 | # text: | # note `|` => multiline string. Use `|-` to strip newlines 28 | # The purpose of this project is to test loading artifact designs. 29 | # 30 | # This is on a new line. 31 | # impl_: null 32 | # subnames: [] 33 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/empty/assert-cases/basic/assert_project_lints.yaml: -------------------------------------------------------------------------------- 1 | error: [] 2 | other: [] 3 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/empty/assert-cases/create-one/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | # no lints 2 | error: [] 3 | other: [] 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/empty/assert-cases/create-one/assert_project.yaml: -------------------------------------------------------------------------------- 1 | # Empty project 2 | # 3 | # This file is also used as a template 4 | settings: 5 | code_paths: [] 6 | exclude_code_paths: [] 7 | 8 | artifact_paths: [ 9 | "design", 10 | ] 11 | exclude_artifact_paths: [] 12 | 13 | code_impls: {} 14 | # TST-pyinit: 15 | # primary: 16 | # file: pylib/__init__.py 17 | # line: 0 18 | # secondary: {} 19 | 20 | artifacts: 21 | REQ-foo: 22 | name: REQ-foo 23 | file: design/purpose.md 24 | partof: [] 25 | parts: [] 26 | completed: {spc: 0.0, tst: 0.0} 27 | text: "This is foo" 28 | impl_: null 29 | subnames: [] 30 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/empty/assert-cases/create-one/assert_project_lints.yaml: -------------------------------------------------------------------------------- 1 | error: [] 2 | other: [] 3 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/empty/assert-cases/create-one/modify.yaml: -------------------------------------------------------------------------------- 1 | - 2 | op: create 3 | artifact: 4 | name: "REQ-foo" 5 | file: "design/purpose.md" 6 | partof: [] 7 | done: null 8 | text: "This is foo" 9 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/empty/design/.empty: -------------------------------------------------------------------------------- 1 | this file exists just so git will keep the folder around 2 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints/.art/settings.toml: -------------------------------------------------------------------------------- 1 | # artifact project settings 2 | 3 | # Note: {cwd} == current directory of THIS file 4 | # {repo} == directory of the `.art` file 5 | 6 | # directories containing artifact toml files 7 | artifact_paths = ["{repo}/design"] 8 | 9 | # artifact paths to exclude. This is how you can avoid trying 10 | # to load .git/.hg/etc directories (or anything else you don't 11 | # want to include 12 | exclude_artifact_paths = [] 13 | 14 | # directories containing code that has artifact links 15 | code_paths = ["/src"] 16 | 17 | # directories to exclude when searching through code 18 | exclude_code_paths = [] 19 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints/assert-cases/basic/assert_project_lints.yaml: -------------------------------------------------------------------------------- 1 | error: 2 | - 3 | level: Error 4 | path: design/purpose.md 5 | line: null 6 | category: Artifact 7 | msg: "REQ-exists defines partof=REQ-dne which does not exist" 8 | - 9 | level: Error 10 | path: design/purpose.md 11 | line: null 12 | category: Artifact 13 | msg: "REQ-exists cannot have `partof` SPC-exists: invalid types." 14 | - 15 | level: Error 16 | path: design/purpose.md 17 | line: null 18 | category: Artifact 19 | msg: "REQ-exists cannot have `partof` TST-exists: invalid types." 20 | - 21 | level: Error 22 | path: design/purpose.md 23 | line: null 24 | category: Artifact 25 | msg: "SPC-exists cannot have `partof` TST-exists: invalid types." 26 | - 27 | level: Error 28 | path: design/purpose.md 29 | line: null 30 | category: Artifact 31 | msg: "TST-exists: subnames are defined when the `done` field is set." 32 | - 33 | level: Error 34 | path: design/text.toml 35 | line: null 36 | category: Artifact 37 | msg: "REQ-text text is invalid: Cannot have a line of the form \"# ART-name\" as that 38 | specifies a new artifact in the markdown format." 39 | - 40 | level: Error 41 | path: design/text.toml 42 | line: null 43 | category: Artifact 44 | msg: "REQ-text text is invalid: Cannot have a line of the form \"###+\" as that 45 | specifies the end of the metadata in the markdown format." 46 | other: 47 | - 48 | level: Warn 49 | path: design/purpose.md 50 | line: null 51 | category: Artifact 52 | msg: "TST-exists has soft reference [[REQ-dne]] which does not exist." 53 | - 54 | level: Warn 55 | path: design/purpose.md 56 | line: null 57 | category: Artifact 58 | msg: "TST-exists has soft reference [[REQ-dne.sub]] which does not exist." 59 | - 60 | level: Warn 61 | path: design/purpose.md 62 | line: null 63 | category: Artifact 64 | msg: "TST-exists has soft reference [[REQ-exists.dne]] which does not exist." 65 | - 66 | level: Warn 67 | path: src/lib.rs 68 | line: 4 69 | category: ImplCode 70 | msg: "Invalid code impl #SPC-exists.dne. Subname [[.dne]] does not exist in artifact's text" 71 | - 72 | level: Warn 73 | path: src/lib.rs 74 | line: 6 75 | category: ImplCode 76 | msg: "Invalid code impl #SPC-dne. Artifact SPC-dne does not exist" 77 | - 78 | level: Warn 79 | path: src/lib.rs 80 | line: 7 81 | category: ImplCode 82 | msg: "Invalid code impl #SPC-dne.sub. Artifact SPC-dne does not exist" 83 | - 84 | level: Warn 85 | path: src/lib.rs 86 | line: 9 87 | category: ImplCode 88 | msg: "Invalid code impl #TST-exists. Artifact's done field is set" 89 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints/design/purpose.md: -------------------------------------------------------------------------------- 1 | # REQ-exists 2 | partof: 3 | - REQ-dne # dne 4 | - SPC-exists # invalid type 5 | - TST-exists # invalid type 6 | ### 7 | 8 | # SPC-exists 9 | partof: 10 | - TST-exists # invalid type 11 | ### 12 | - [[.sub]]: has a sub, horray 13 | 14 | # TST-exists 15 | done: "this is done baby" 16 | ### 17 | but... also has subparts 18 | [[.foo]] 19 | 20 | ## Invalid references 21 | [[REQ-dne]] [[REQ-dne.sub]] 22 | 23 | [[REQ-exists.dne]] 24 | 25 | ## Valid references 26 | [[REQ-exists]] 27 | 28 | [[SPC-exists]] [[SPC-exists.sub]] 29 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints/design/text.toml: -------------------------------------------------------------------------------- 1 | [REQ-text] 2 | text = """ 3 | This has some invalid text 4 | 5 | # REQ-foo 6 | ^^^ doesn't work in markdown 7 | 8 | ### 9 | ^^^ also doesn't work in markdown. 10 | """ 11 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints/src/lib.rs: -------------------------------------------------------------------------------- 1 | // a library to link to things 2 | // 3 | // #SPC-exists -- yay we got one right! 4 | // #SPC-exists.sub -- another one, on a role baby 5 | // #SPC-exists.dne -- oops, oh well! 6 | // 7 | // #SPC-dne -- boo 8 | // #SPC-dne.sub -- double boo 9 | // 10 | // #TST-exists -- has `done` set 11 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/.art/settings.toml: -------------------------------------------------------------------------------- 1 | # artifact project settings 2 | 3 | # Note: {cwd} == current directory of THIS file 4 | # {repo} == directory of the `.art` file 5 | 6 | # directories containing artifact toml files 7 | artifact_paths = ["{repo}/design"] 8 | 9 | # artifact paths to exclude. This is how you can avoid trying 10 | # to load .git/.hg/etc directories (or anything else you don't 11 | # want to include 12 | exclude_artifact_paths = [] 13 | 14 | # directories containing code that has artifact links 15 | code_paths = ["/src"] 16 | 17 | # directories to exclude when searching through code 18 | exclude_code_paths = [] 19 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "basic" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "basic" 3 | version = "0.1.0" 4 | authors = ["Garrett Berg "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/README.md: -------------------------------------------------------------------------------- 1 | The reason for this test's existance is primarily because the lints in the first lint test 2 | were causing some code to not even be executed. 3 | 4 | TODO: why was the graphing code not executed with the lints in the interop lints. 5 | 6 | Also, this should a strong need to finish fuzz testing for whole projects. 7 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/assert-cases/basic/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | error: 2 | - 3 | level: Error 4 | path: design/purpose.md 5 | line: null 6 | category: Artifact 7 | msg: "SPC-partof_dne defines partof=SPC-dne which does not exist" 8 | other: [] 9 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/assert-cases/basic/assert_project.yaml: -------------------------------------------------------------------------------- 1 | # Basic project 2 | # 3 | # This contains a "sunny day" project with no errors for basic testing of 4 | # - loading artifact 5 | # - linking artifacts to source code 6 | settings: 7 | code_paths: 8 | - src 9 | 10 | exclude_code_paths: [] 11 | 12 | artifact_paths: 13 | - design 14 | 15 | exclude_artifact_paths: [] 16 | 17 | code_impls: {} 18 | artifacts: 19 | SPC-partof_dne: 20 | name: SPC-partof_dne 21 | file: design/purpose.md 22 | partof: 23 | - SPC-dne 24 | parts: [] 25 | completed: 26 | spc: 0 27 | tst: 0 28 | text: | 29 | 30 | This specification's partof does not exist. 31 | 32 | impl_: null 33 | subnames: [] 34 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/assert-cases/basic/assert_project_lints.yaml: -------------------------------------------------------------------------------- 1 | error: 2 | - 3 | level: Error 4 | path: design/purpose.md 5 | line: null 6 | category: Artifact 7 | msg: "SPC-partof_dne defines partof=SPC-dne which does not exist" 8 | other: [] 9 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/design/purpose.md: -------------------------------------------------------------------------------- 1 | # SPC-partof_dne 2 | partof: SPC-dne 3 | ### 4 | 5 | This specification's partof does not exist. 6 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/target/.rustc_info.json: -------------------------------------------------------------------------------- 1 | {"rustc_fingerprint":15893297361853315868,"outputs":{"15337506775154344876":["___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/garrett/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"mmx\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nunix\n",""],"1164083562126845933":["rustc 1.28.0-nightly (967c1f3be 2018-06-15)\nbinary: rustc\ncommit-hash: 967c1f3be1c9ce0469ae9e30659bdf4da5346a9f\ncommit-date: 2018-06-15\nhost: x86_64-unknown-linux-gnu\nrelease: 1.28.0-nightly\nLLVM version: 6.0\n",""],"1617349019360157463":["___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/garrett/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"mmx\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nunix\n",""]}} -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/target/debug/.cargo-lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/artifact-test/interop_tests/lints2/target/debug/.cargo-lock -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/target/debug/build/basic-2ccdec1e4884b553/build_script_build-2ccdec1e4884b553.d: -------------------------------------------------------------------------------- 1 | /home/garrett/code/artifact/artifact-test/interop_tests/warning/target/debug/build/basic-2ccdec1e4884b553/build_script_build-2ccdec1e4884b553: build.rs 2 | 3 | /home/garrett/code/artifact/artifact-test/interop_tests/warning/target/debug/build/basic-2ccdec1e4884b553/build_script_build-2ccdec1e4884b553.d: build.rs 4 | 5 | build.rs: 6 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/lints2/target/debug/incremental/build_script_build-2mpg4k3gfwhp5/s-f2qdvys262-ewn7ea.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/artifact-test/interop_tests/lints2/target/debug/incremental/build_script_build-2mpg4k3gfwhp5/s-f2qdvys262-ewn7ea.lock -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/.art/settings.toml: -------------------------------------------------------------------------------- 1 | # artifact project settings 2 | 3 | # directories containing artifact toml files 4 | artifact_paths = ["{repo}/design"] 5 | 6 | # artifact paths to exclude. This is how you can avoid trying 7 | # to load .git/.hg/etc directories (or anything else you don't 8 | # want to include 9 | exclude_artifact_paths = [] 10 | 11 | # directories containing code that has artifact links 12 | code_paths = ["/src", "/build.rs"] 13 | 14 | # directories to exclude when searching through code 15 | exclude_code_paths = [] 16 | 17 | [parse] 18 | md_name = { type = "prefix", value = "#" } 19 | 20 | [format] 21 | md_attrs = {type = "code", prefix = "yaml"} 22 | 23 | [export] 24 | md_name = { type = "prefix", value = "#" } 25 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "basic" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "basic" 3 | version = "0.1.0" 4 | authors = ["Garrett Berg "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/assert-cases/basic/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | # no lints 2 | error: [] 3 | other: [] 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/assert-cases/basic/assert_project_lints.yaml: -------------------------------------------------------------------------------- 1 | error: [] 2 | other: [] 3 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/build.rs: -------------------------------------------------------------------------------- 1 | //! #SPC-build 2 | //! 3 | //! Build file, included by direct path 4 | 5 | // And some test: #TST-build (but not subpart) 6 | // Also a unit test: #SPC-build.tst-unit 7 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/design/foo.md: -------------------------------------------------------------------------------- 1 | ## SPC-foo 2 | This is the spec for foo, it does lots of foo. 3 | 4 | It is some foo subparts: 5 | - [[.no]]: not done 6 | - [[.yes]]: done 7 | 8 | 9 | ## SPC-foo_done 10 | ```yaml art 11 | done: this is done 12 | 13 | partof: 14 | - REQ-foo 15 | - SPC-foo 16 | ``` 17 | This is done and is weird? 18 | 19 | 20 | ## TST-foo 21 | Partially done foo test with some subparts 22 | 23 | - [[.no1]] 24 | - [[.no2]] 25 | - [[.yes1]] 26 | - [[.yes2]] 27 | - [[.yes3]] 28 | - [[.yes4]] -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/design/purpose.md: -------------------------------------------------------------------------------- 1 | ## REQ-baz 2 | implemented directly in source! 3 | 4 | Not a partof anything... 5 | 6 | 7 | ## REQ-foo 8 | ```yaml art 9 | partof: REQ-purpose 10 | ``` 11 | foo needs to do the foo thing 12 | 13 | 14 | ## REQ-lib 15 | ```yaml art 16 | partof: REQ-purpose 17 | ``` 18 | Lib is definitely a library 19 | 20 | 21 | ## REQ-purpose 22 | The purpose of this project is is to test a basic 23 | project... that's it! 24 | 25 | 26 | ## SPC-build 27 | ```yaml art 28 | partof: REQ-purpose 29 | ``` 30 | This has a build file. 31 | 32 | Unit tests: 33 | - [[.tst-unit]] 34 | 35 | 36 | ## TST-build 37 | ```yaml art 38 | partof: REQ-purpose 39 | ``` 40 | direct link to REQ-purpose 41 | 42 | - [[.no]] -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/src/baz.rs: -------------------------------------------------------------------------------- 1 | /// #REQ-baz 2 | /// Just implement baz directly 3 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/src/foo/fab.rs: -------------------------------------------------------------------------------- 1 | //! This has foo stuff 2 | 3 | 4 | /// #SPC-foo.yes 5 | /// Do foo? 6 | fn foo() { 7 | } 8 | 9 | #[test] 10 | /// #TST-foo.yes4 11 | fn test_samefile() { 12 | println!("TST-foo"); // nothing happens without `#` 13 | } 14 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/src/foo/mod.rs: -------------------------------------------------------------------------------- 1 | /// #SPC-foo 2 | /// 3 | /// This is where foo is implemented 4 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/src/foo/test.rs: -------------------------------------------------------------------------------- 1 | /// Test foo and stuff. Don't link TST-foo directly 2 | 3 | 4 | #[test] 5 | /// #TST-foo.yes1 6 | fn foo_1() { 7 | // #TST-foo.yes2 8 | // #TST-foo.yes3 9 | } 10 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/settings/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_invalid/.art/settings.toml: -------------------------------------------------------------------------------- 1 | # artifact project settings 2 | 3 | # Note: {cwd} == current directory of THIS file 4 | # {repo} == directory of the `.art` file 5 | 6 | # directories containing artifact toml files 7 | artifact_paths = [] 8 | 9 | # artifact paths to exclude. This is how you can avoid trying 10 | # to load .git/.hg/etc directories (or anything else you don't 11 | # want to include 12 | exclude_artifact_paths = [] 13 | 14 | # directories containing code that has artifact links 15 | code_paths = ["/src"] 16 | 17 | # directories to exclude when searching through code 18 | exclude_code_paths = [] 19 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_invalid/assert-cases/basic/assert_load_lints.yaml: -------------------------------------------------------------------------------- 1 | error: 2 | - 3 | level: Error 4 | path: src/one.py 5 | line: 2 6 | category: ParseCodeImplementations 7 | msg: "duplicate detected: SPC-one" 8 | - 9 | level: Error 10 | path: src/one.py 11 | line: 3 12 | category: ParseCodeImplementations 13 | msg: "duplicate detected: SPC-one" 14 | - 15 | level: Error 16 | path: src/two.py 17 | line: 2 18 | category: ParseCodeImplementations 19 | msg: "duplicate detected: SPC-two" 20 | - 21 | level: Error 22 | path: src/two.py 23 | line: 3 24 | category: ParseCodeImplementations 25 | msg: "duplicate detected: SPC-two.a" 26 | - 27 | level: Error 28 | path: src/two-b.py 29 | line: 2 30 | category: ParseCodeImplementations 31 | msg: "duplicate detected: SPC-two" 32 | - 33 | level: Error 34 | path: src/two-b.py 35 | line: 3 36 | category: ParseCodeImplementations 37 | msg: "duplicate detected: SPC-two.a" 38 | other: [] 39 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_invalid/src/one.py: -------------------------------------------------------------------------------- 1 | # This has two identical locations 2 | 3 | #SPC-one 4 | #SPC-one 5 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_invalid/src/two-b.py: -------------------------------------------------------------------------------- 1 | # The other identical location 2 | 3 | #SPC-two 4 | #SPC-two.a 5 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_invalid/src/two.py: -------------------------------------------------------------------------------- 1 | # This has one of the identical ones 2 | 3 | #SPC-two 4 | #SPC-two.a 5 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_only/.art/settings.toml: -------------------------------------------------------------------------------- 1 | # artifact project settings 2 | 3 | # Note: {cwd} == current directory of THIS file 4 | # {repo} == directory of the `.art` file 5 | 6 | # directories containing artifact toml files 7 | artifact_paths = [] 8 | 9 | # artifact paths to exclude. This is how you can avoid trying 10 | # to load .git/.hg/etc directories (or anything else you don't 11 | # want to include 12 | exclude_artifact_paths = [] 13 | 14 | # directories containing code that has artifact links 15 | code_paths = ["src", "pylib/"] 16 | 17 | # directories to exclude when searching through code 18 | exclude_code_paths = ["pylib/noinclude", "pylib/noinclude.py"] 19 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_only/assert-cases/basic/assert_project.yaml: -------------------------------------------------------------------------------- 1 | # Source only example project. 2 | # 3 | # This just asserts that the source files are parsed as expected. 4 | settings: 5 | code_paths: 6 | - pylib 7 | - src 8 | exclude_code_paths: 9 | - pylib/noinclude 10 | - pylib/noinclude.py 11 | artifact_paths: [] 12 | exclude_artifact_paths: [] 13 | code_impls: 14 | TST-pyinit: 15 | primary: 16 | file: pylib/__init__.py 17 | line: 0 18 | secondary: {} 19 | SPC-pylib: 20 | primary: null 21 | secondary: 22 | .example: 23 | file: pylib/example.py 24 | line: 1 25 | REQ-rust: 26 | primary: 27 | file: src/lib.rs 28 | line: 0 29 | secondary: {} 30 | artifacts: {} 31 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_only/pylib/__init__.py: -------------------------------------------------------------------------------- 1 | #TST-pyinit 2 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_only/pylib/example.py: -------------------------------------------------------------------------------- 1 | # this is an example. 2 | # #SPC-pylib.example 3 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_only/pylib/noinclude.py: -------------------------------------------------------------------------------- 1 | #SPC-not_here 2 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_only/pylib/noinclude/foo.py: -------------------------------------------------------------------------------- 1 | #SPC-not_here 2 | -------------------------------------------------------------------------------- /artifact-test/interop_tests/source_only/src/lib.rs: -------------------------------------------------------------------------------- 1 | #REQ-rust 2 | -------------------------------------------------------------------------------- /artifact-test/src/artifact.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! This module is for testing fully realized artifacts. 18 | 19 | use super::dev_prelude::*; 20 | use super::implemented::random_impl_links; 21 | use super::raw::arb_raw_artifacts; 22 | use artifact_lib::*; 23 | 24 | const GEN_REL_FILE_PATH_RE: &str = r#"(?x) 25 | ([a-zA-Z0-9_]{1,7}/){0,3} # an optional number of subdirs 26 | [a-zA-Z0-9_]{1,7}.(md|json|toml) # the required file name 27 | "#; 28 | 29 | pub fn arb_rel_file_path() -> BoxedStrategy { 30 | GEN_REL_FILE_PATH_RE.prop_map(|s| s.to_string()).boxed() 31 | } 32 | 33 | /// Arbitrary _relative_ file paths. 34 | /// 35 | /// Always generates at least 1. size must be `> 0` 36 | pub fn arb_rel_file_paths(size: usize) -> BoxedStrategy> { 37 | prop::collection::hash_set(arb_rel_file_path(), 1..size).boxed() 38 | } 39 | 40 | // TODO: use the file paths above to construct the artifacts. 41 | // pub fn arb_artifacts(size: usize) -> BoxedStrategy> { 42 | // arb_raw_artifacts(size) 43 | // .prop_perturb(|artifacts, mut rng| { 44 | // unimplemented!() 45 | // }) 46 | // .boxed() 47 | // } 48 | 49 | // fn get_settings(raw: BTreeMap) -> (Settings, BTreeMap) { 50 | // unimplemented!(); 51 | // } 52 | -------------------------------------------------------------------------------- /artifact-test/src/graph.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! This module defines tests for the graph implementation details of 18 | //! computing artifacts. 19 | 20 | use super::dev_prelude::*; 21 | use artifact_data::graph::{self, round_ratio}; 22 | 23 | /// create the `partof`s and the graphs 24 | pub fn simple_graph() -> (IndexMap>, graph::Graphs) { 25 | let partofs = indexmap! { 26 | name!("REQ-aaa") => indexset!{}, 27 | name!("REQ-bbb") => indexset!{name!("REQ-aaa")}, 28 | name!("REQ-ccc") => indexset!{name!("REQ-bbb")}, 29 | name!("SPC-bbb") => indexset!{name!("REQ-bbb")}, 30 | name!("SPC-bbb-a") => indexset!{name!("SPC-bbb")}, 31 | name!("SPC-bbb-b") => indexset!{name!("SPC-bbb")}, 32 | name!("TST-aaa") => indexset!{name!("SPC-bbb")}, 33 | name!("TST-aaa-a") => indexset!{name!("TST-aaa")}, 34 | }; 35 | 36 | let graphs = graph::determine_graphs(&partofs); 37 | (partofs, graphs) 38 | } 39 | -------------------------------------------------------------------------------- /artifact-test/src/implemented.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | /// Test the "implemented" (i.e. source code parsing) module. 18 | use regex_generate; 19 | 20 | use super::dev_prelude::*; 21 | use super::raw_names::arb_names_raw; 22 | use artifact_data::implemented::{join_locations, parse_locations}; 23 | use artifact_data::raw_names::NamesRaw; 24 | 25 | // ------------------------------ 26 | // -- FUZZ METHODS 27 | 28 | /// Generate a list of names along with randomly generated sub-names. 29 | /// 30 | /// It is guaranteed that all names are represented. 31 | pub fn random_impl_links( 32 | rng: &mut R, 33 | names: &NamesRaw, 34 | ) -> IndexSet<(Name, Option)> { 35 | let mut textgen = 36 | regex_generate::Generator::parse(r"\.((tst-)?[a-zA-Z0-9_]{1,10})", rng.clone()).unwrap(); 37 | let mut buffer: Vec = Vec::with_capacity(10); 38 | let mut out = IndexSet::new(); 39 | for name in names.iter() { 40 | // Base name is always included 41 | out.insert((name.clone(), None)); 42 | if rng.next_f32() < 0.3 { 43 | // 30% chance ahere are no subnames 44 | continue; 45 | } 46 | for _ in 0..rng.gen_range(1, 5) { 47 | buffer.clear(); 48 | textgen.generate(&mut buffer).unwrap(); 49 | let sub = subname!(str::from_utf8(&buffer).unwrap()); 50 | out.insert((name.clone(), Some(sub))); 51 | } 52 | } 53 | out 54 | } 55 | 56 | /// Generate random source code text with links to all the given `name[.sub]`s. 57 | pub fn random_source_code( 58 | rng: &mut R, 59 | locations: &IndexSet<(Name, Option)>, 60 | ) -> String { 61 | let mut lines = random_lines(rng); 62 | if lines.is_empty() { 63 | lines.push(vec!["".into()]); 64 | } 65 | for &(ref name, ref sub) in locations.iter() { 66 | insert_word(rng, &mut lines, format!("#{}", name_ref_string(name, sub))); 67 | } 68 | lines.iter().map(|line| line.iter().join(" ")).join("\n") 69 | } 70 | 71 | /// Arbitrary single source code file 72 | pub fn arb_source_code( 73 | size: usize, 74 | ) -> BoxedStrategy<(NamesRaw, IndexSet<(Name, Option)>, String)> { 75 | arb_names_raw(size) 76 | .prop_perturb(|names, mut rng| { 77 | let locations = random_impl_links(&mut rng, &names); 78 | let code = random_source_code(&mut rng, &locations); 79 | (names, locations, code) 80 | }) 81 | .boxed() 82 | } 83 | 84 | // METHODS 85 | 86 | pub fn replace_links(raw: &str) -> String { 87 | raw.replace('%', "#") 88 | } 89 | -------------------------------------------------------------------------------- /artifact-test/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! This subcrate is to provide a common testing framework/functions 18 | //! for testing artifact. 19 | //! 20 | //! Related: 21 | //! - #TST-unit 22 | //! - #TST-fuzz 23 | #![allow(unused_imports)] 24 | #![allow(dead_code)] 25 | #![allow(unused_macros)] 26 | 27 | pub use base64; 28 | pub use ergo; 29 | #[macro_use] 30 | pub extern crate expect_macro; 31 | pub use failure; 32 | #[macro_use] 33 | pub extern crate matches; 34 | pub use petgraph; 35 | pub use rayon; 36 | pub use siphasher; 37 | 38 | #[macro_use] 39 | pub extern crate failure_derive; 40 | pub use time; 41 | 42 | #[macro_use] 43 | pub extern crate artifact_data; 44 | #[macro_use] 45 | pub extern crate artifact_lib; 46 | #[macro_use] 47 | extern crate log; 48 | 49 | #[macro_use] 50 | extern crate proptest; 51 | 52 | #[macro_use] 53 | extern crate pretty_assertions; 54 | 55 | // #[cfg(test)] 56 | // extern crate rand; 57 | 58 | use regex_generate; 59 | 60 | pub mod artifact; 61 | pub mod dev_prelude; 62 | pub mod family; 63 | pub mod graph; 64 | pub mod implemented; 65 | pub mod name; 66 | pub mod raw; 67 | #[macro_use] 68 | pub mod raw_names; 69 | pub mod framework; 70 | 71 | pub use crate::dev_prelude::*; 72 | pub use crate::framework::{ 73 | assert_stuff_data, run_generic_interop_test, run_generic_interop_tests, ExpectStuff, 74 | }; 75 | pub use artifact_data::*; // for macros 76 | pub use proptest::*; 77 | -------------------------------------------------------------------------------- /artifact-test/src/name.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | //! This module defines all operations around testing artifact names 18 | 19 | use ergo::json; 20 | 21 | use super::dev_prelude::*; 22 | 23 | // HELPERS and TRAITS 24 | 25 | // this purposely doesn't use the definition from `name.rs` 26 | const GEN_NAME_RE: &str = r#"(?x) 27 | (REQ|SPC|TST)- # the type followed by `-` 28 | ([a-zA-Z0-9_]{1,7}-){0,3} # an optional number of `elem-` elements 29 | [a-zA-Z0-9_]{1,7} # required final element 30 | "#; 31 | 32 | // lazy_static!{ 33 | // static ref GEN_NAME_PROP: Arc> = 34 | // Arc::new(prop::string::string_regex(GEN_NAME_RE).unwrap()); 35 | // } 36 | 37 | #[inline(always)] 38 | pub fn arb_name_string() -> BoxedStrategy { 39 | GEN_NAME_RE.prop_map(|s| s.to_string()).boxed() 40 | } 41 | 42 | #[inline(always)] 43 | pub fn arb_name() -> BoxedStrategy { 44 | arb_name_string().prop_map(|n| name!(n)).boxed() 45 | } 46 | 47 | /// Return a vector of the `raw` names 48 | pub fn names_raw(names: &[Name]) -> Vec { 49 | names.iter().map(|n| n.raw.clone()).collect() 50 | } 51 | 52 | /// Assert that the name is valid 53 | pub fn assert_names_valid(raw: &[&str]) { 54 | let errors = raw 55 | .iter() 56 | .map(|r| (*r, Name::from_str(r))) 57 | .filter_map(|(raw, result)| match result { 58 | Ok(name) => { 59 | if raw == name.raw { 60 | None 61 | } else { 62 | panic!("raw was different: {} => {}", raw, name.raw); 63 | } 64 | } 65 | Err(_) => Some(raw), 66 | }) 67 | .collect::>(); 68 | if !errors.is_empty() { 69 | panic!("The following names were not valid:\n{:#?}", errors); 70 | } 71 | } 72 | 73 | /// Assert that the name is valid 74 | pub fn assert_names_invalid(raw: &[&str]) { 75 | let errors = raw 76 | .iter() 77 | .map(|r| (r, Name::from_str(r))) 78 | .filter_map(|(raw, result)| match result { 79 | Ok(_) => Some(raw), 80 | Err(_) => None, 81 | }) 82 | .collect::>(); 83 | if !errors.is_empty() { 84 | panic!( 85 | "The following names were valid but shouldn't have been:\n{:#?}", 86 | errors 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /artifact-test/src/raw_names.rs: -------------------------------------------------------------------------------- 1 | /* artifact: the requirements tracking tool made for developers 2 | * Copyright (C) 2018 Rett Berg <@vitiral, vitiral@gmail.com> 3 | * 4 | * The source code is Licensed under either of 5 | * 6 | * * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 7 | * http://www.apache.org/licenses/LICENSE-2.0) 8 | * * MIT license ([LICENSE-MIT](LICENSE-MIT) or 9 | * http://opensource.org/licenses/MIT) 10 | * 11 | * at your option. 12 | * 13 | * Unless you explicitly state otherwise, any contribution intentionally submitted 14 | * for inclusion in the work by you, as defined in the Apache-2.0 license, shall 15 | * be dual licensed as above, without any additional terms or conditions. 16 | * */ 17 | 18 | //! Test serializing/deserializing raw names 19 | 20 | use ergo::{json, toml, yaml}; 21 | 22 | use super::dev_prelude::*; 23 | use super::name::arb_name; 24 | use artifact_data::raw_names::NamesRaw; 25 | 26 | pub fn arb_names_raw(size: usize) -> BoxedStrategy { 27 | prop::collection::hash_set(arb_name(), 0..size) 28 | .prop_map(|hs| NamesRaw::from(hs)) 29 | .boxed() 30 | } 31 | -------------------------------------------------------------------------------- /book/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | -------------------------------------------------------------------------------- /book/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Garrett Berg"] 3 | multilingual = false 4 | src = "src" 5 | title = "Simple Quality with Artifact" 6 | 7 | [build] 8 | build-dir = "out/book" 9 | -------------------------------------------------------------------------------- /book/src/Addendum.md: -------------------------------------------------------------------------------- 1 | # Addendum 2 | 3 | This section contains the addendum to this guide, including the spec, FAQ and 4 | other materials. 5 | 6 | -------------------------------------------------------------------------------- /book/src/ArtifactIntro.md: -------------------------------------------------------------------------------- 1 | # Artifact Intro 2 | 3 | This is an introduction to how we start integrating the Artifact tool into our 4 | design and development workflow. It is intended to be interactive, so please 5 | follow along with everything installed! 6 | 7 | > **Exercise 1: ensuring your environment works:** 8 | > 9 | > You should have at least done the [Starting Project](./StartingProject.html) 10 | > chapter before attempting this one. 11 | > 12 | > Run `art ls`, you should see something like: 13 | > 14 | > ``` 15 | > spc% tst% | name | parts 16 | > 0.0 0.0 | REQ-purpose | 17 | > ``` 18 | 19 | ## Converting our README.md into an artifact. 20 | 21 | The first thing we want to do is use the `README.md` file we have already been writing 22 | as our artifact file. 23 | 24 | To do this, let's make a couple of changes: 25 | - Move our `README.md` into `design/purpose.md` 26 | - Clean up the headers so they are artifacts. 27 | 28 | To move your README.md, simply type: 29 | ``` 30 | mv README.md purpose.md 31 | ``` 32 | 33 | > **Check In:** run `art ls`. It shows nothing because we have not specified 34 | > any artifacts. 35 | 36 | We now need to convert our headers into artifacts. Let's start with our purpose. 37 | Change the `# Purpose` line (from [Specifying Your Purpose](./Purpose.html)) to 38 | `# REQ-purpose`. Your file should now look something like: 39 | 40 | ```markdown 41 | # REQ-purpose 42 | Write a flash card quizzer ... 43 | 44 | ``` 45 | 46 | Do the same thing to your specifications from 47 | [High Level Design](./Design.html): 48 | - `# Execution Method` -> `# SPC-cli` 49 | - `# Final Results` -> `# SPC-report` 50 | - `# Question File Format` -> `# SPC-format` 51 | 52 | Now `art ls` should show: 53 | ```bash 54 | $ art ls 55 | spc% tst% | name | parts 56 | 0.0 0.0 | REQ-purpose | 57 | 0.0 0.0 | SPC-cli | 58 | 0.0 0.0 | SPC-format | 59 | 0.0 0.0 | SPC-report | 60 | ``` 61 | 62 | This is closer, but notice that none of them are linked. Let's fix that. 63 | 64 | For `SPC-cli` make it look like this: 65 | 66 | ```markdown 67 | # SPC-cli 68 | partof: 69 | - REQ-purpose 70 | ### 71 | The minimum viable product ... 72 | ``` 73 | 74 | Do the same for `SPC-format` and `SPC-report`, also making them partof 75 | `REQ-purpose`. You should now have: 76 | ``` 77 | $ art ls 78 | spc% tst% | name | parts 79 | 0.0 0.0 | REQ-purpose | SPC-cli, SPC-format, SPC-report 80 | 0.0 0.0 | SPC-cli | 81 | 0.0 0.0 | SPC-format | 82 | 0.0 0.0 | SPC-report | 83 | 84 | ``` 85 | 86 | Now is also a good time to run `art serve`. This will serve your project 87 | locally so that you can view and edit it through the Web UI. 88 | 89 | [Here is an example of the project in its current state](examples/part1/index.html) 90 | 91 | 92 | -------------------------------------------------------------------------------- /book/src/BestPractices.md: -------------------------------------------------------------------------------- 1 | These are a few of the (alpha) best practices when using artifact. 2 | 3 | ### use-features: use the features of artifact 4 | Artifact contains several useful features. Use them! 5 | - `art check`: makes sure your references are all valid both in code and in your 6 | artifacts. 7 | - `art fmt`: format your artifacts 8 | 9 | ### too-many-pieces: Do not break into too many pieces 10 | Artifact is a great tool for breaking up your design, so much so that it is 11 | tempting to specify every detail as it's own artifact 12 | 13 | Avoid this: 14 | - SPC-ui-cmd 15 | - SPC-ui-cmd-ls 16 | - SPC-ui-cmd-fmt 17 | - SPC-ui-web 18 | - SPC-ui-web-list 19 | - SPC-ui-web-edit 20 | - SPC-ui-gui 21 | - ... etc... 22 | 23 | There is no reason to have the `ui` prefix -- each of these are almost 24 | completely different components and doesn't aid in understanding your 25 | design documents. 26 | 27 | Instead, consider having: 28 | 29 | - REQ-ui: high level ui requirements 30 | - REQ-cmd: partof=REQ-ui 31 | - REQ-web: partof=REQ-ui 32 | - REQ-gui: partof=REQ-ui 33 | 34 | This keeps the breakdown obvious but also keeps the names short. 35 | 36 | ### short-names: Keep artifact names as short as possible 37 | Nobody wants to read `REQ-ui-web-design-frontend-edit-text`. That level of 38 | nesting is simply not necessary. Something like `REQ-web-edit` will suffice. 39 | 40 | Try and combine such detail into a single artifact. Auto-linking is cool, but 41 | don't get carried away! It's okay to specify `partof` when it makes 42 | your tree simpler. 43 | 44 | ### no-numbers: Use only human readable names 45 | Artifact names should avoid using numbers. If you are tempted to call something 46 | `SPC-foo-1` just break down the different items of `foo` in a bullet point list 47 | in its `text` field and use subnames. 48 | 49 | ### abbreviations: abbreviate names 50 | Artifact is intended to be used as a cmd line tool, so keeping names short is 51 | very nice. 52 | 53 | This is mostly useful for larger projects. 54 | 55 | ### prefix-acronyms: create acronyms for your prefixes 56 | Use an acronym or abbreviation for your prefixes. 57 | 58 | One of the main use cases of short names is for the categories of your 59 | artifacts. For instance, say your storage product had the following features: 60 | - transport 61 | - data availability 62 | - data recovery 63 | - remote replication 64 | 65 | It would be annoying to have artifacts like `REQ-transport-drive` or 66 | `REQ-remote_replication-protocol`. Instead, use an acronyms: 67 | 68 | - **TP**: transport 69 | - **DA**: data availability 70 | - **DR**: data recovery 71 | - **RR**: remote replication 72 | 73 | Now your artifacts look like `REQ-TP-drive` and `REQ-RR-protocol`, 74 | which is much shorter and more readable when looking at a large list. 75 | 76 | ### uniformity: keep names uniform 77 | Artifact automatically makes `SPC-foo` a partof `REQ-foo` and that is because 78 | they should be related. Make sure your names have meaning so this doesn't 79 | accidentally become a gotcha for your project. 80 | 81 | -------------------------------------------------------------------------------- /book/src/CleaningUp.md: -------------------------------------------------------------------------------- 1 | # Cleaning Up 2 | There are two more commands that it is critical to know: 3 | - `art check`: for checking for errors and warnings. 4 | - `art fmt`: for formatting your arguments. 5 | 6 | `art check` checks a whole range of things: 7 | - All artifacts in `partof` exist. 8 | - The soft references (i.e. `[[REQ-foo]]`) exist. 9 | - Code references are valid and not duplicated. 10 | 11 | `art fmt` standardizes the format of your artifacts and makes them easier to read. 12 | 13 | > Note: `art fmt` is automatically run whenever you edit any artifacts via the 14 | > Web UI. 15 | 16 | 17 | ## Documenting and Hosting your own project 18 | To start documenting your own project, run `art init` in your project and 19 | edit `.art/settings.toml` with the paths on where to find your 20 | design docs and code. 21 | 22 | Have your build system export your design documents as html for easy viewing. 23 | See: [Exporting Html](./ExportingHtml.html) 24 | 25 | 26 | ## Artifact Advice 27 | Here are a words when using artifact: 28 | 29 | 1. You should always write a good README and other documentation for your users 30 | -- design docs SHOULD be used for bringing developers of your project up 31 | to speed but they aren't the best format for general users. 32 | 2. Keep your design docs fairly high level -- don't try to design every detail 33 | using artifact. Using artifact does not mean that you shouldn't use code 34 | comments! 35 | 3. Use `art ls` and `art check` often, and fix those error messages! 36 | 4. Follow the [artifact best practices](./BestPractices.html). 37 | 5. Don't be afraid to refactor your design docs. It is actually easier than it 38 | might sound, as the tool will help you find broken links and incomplete 39 | items in real time. Not to mention that if you use revision control 40 | (you should), your artifacts can be tracked with your project -- no more 41 | having your documentation and your code be wildly out of sync! 42 | 43 | This tutorial took you part of the way through developing a simple project 44 | using artifact. Continue onto the next section or simply try using artifact for 45 | one of your smaller personal projects and see the benefits that design 46 | documents can give -- it's your choice! 47 | 48 | Have some fun with the tool, try to break it. If you find bugs or have any 49 | suggestions, please open a ticket at: 50 | https://github.com/vitiral/artifact/issues 51 | 52 | Good luck! 53 | -------------------------------------------------------------------------------- /book/src/Design.md: -------------------------------------------------------------------------------- 1 | # High Level Design 2 | 3 | Once you know the purpose of your project, it is important for you to write 4 | down the approach you plan to take. This is important because: 5 | - There may be gaps when you don't work on your project. If you go on vacation 6 | for a month, having a reference of your thoughts at the time you were focused 7 | can jumpstart your productivity. 8 | - It is important to be able to reference a design doc for new contributors and 9 | newbie developers. 10 | 11 | Your high level requirements should go in your `README.md`, just below your purpose 12 | section: 13 | 14 | ```markdown 15 | # Execution Method 16 | The minimum viable product shall be a command line utility 17 | that is given the path to one or more question files as 18 | arguments 19 | 20 | Additional arguments will include: 21 | - `-t`: specify the time allowed for each question 22 | - `-T`: specify the total time allowed for the whole quiz 23 | - `-r NUM`: repeat questions only a certain number of times. 24 | By default there is no limit 25 | 26 | The program will ask one question at a time, recording how 27 | many answers the user got correct/incorrect and weighting 28 | future questions accordingly. 29 | 30 | When the program is complete it will report: 31 | - time taken, broken up by whole quiz and each question 32 | - the user's score 33 | 34 | 35 | # Final Results 36 | When the program is complete a report shall be printed with: 37 | - time taken, broken up by whole quiz and each question 38 | - the user's total score 39 | - questions ranked by ones the user had the most difficulty 40 | 41 | 42 | # Question File Format 43 | The user shall be able to easily configure the quiz 44 | questions through a simple csv format consisting of two 45 | columns: the question and the answer. 46 | ``` 47 | 48 | Again, just like the purpose documentation, this documentation aims to be 49 | brief and help you during your design process. 50 | 51 | > ### Exercise 1: 52 | > What are some other items that we can detail at a high level? 53 | > Try writing them out yourself in this section. 54 | -------------------------------------------------------------------------------- /book/src/DetailedDesign.md: -------------------------------------------------------------------------------- 1 | # Detailed Design 2 | 3 | Now that we have our high level design, let's start desiging how we are 4 | actually going to _build_ our flash card application. The first thing 5 | we might want to design is: how does the user specify questions? 6 | 7 | We already answered this to some degree in `SPC-format`. Let's expand it a bit. 8 | 9 | ```markdown 10 | # SPC-format 11 | partof: 12 | - REQ-purpose 13 | ### 14 | The user shall be able to easily configure the quiz 15 | questions through a simple csv format consisting of two 16 | columns: the question and the answer. 17 | 18 | The format of the csv file **shall** be a csv file of the form: 19 | 20 | City, Capitol 21 | 22 | > Note: whitespace will be ignored 23 | 24 | ## [[.question]] 25 | The `Question` class shall be the primary datatype used for questions in the 26 | application. Quetions shall: 27 | - Store the question and answer. 28 | - Provide a method `ask` to ask the user the question 29 | and validate the answer. 30 | 31 | ## [[.validate]] 32 | Input questions **shall** be validated to: 33 | - Guarantee against duplicates. 34 | - Guarantee that the data format is correct. 35 | ``` 36 | 37 | There are a few things here, so let's take a look: 38 | - We expanded _how_ the user can configure the questions (the CSV format itself) 39 | - We created two subartifacts, `.question` and `.validate`. 40 | - Having the `[[.subart]]` anywhere within the text is enough to create 41 | these. 42 | - We can now link these subarts in code and they are necessary for our 43 | artifact to be considered "complete". 44 | 45 | # Define Tests 46 | 47 | Let's also define a couple of unit tests. You could do this using a new 48 | `TST-format` (or any other name) artifact. 49 | 50 | However, artifact has what are called tst-subarts specifically for the purpose 51 | of defining unit test coverage that you want. Simply add the following section 52 | to `SPC-format`: 53 | 54 | ```markdown 55 | ## Unit Tests: 56 | - Invalid: make sure invalid inputs don't work 57 | - [[.tst-invalid_cols]]: Test invalid number of columns (0, 1, and 3). 58 | - [[.tst-duplicates]]: Test duplicate names. 59 | - Make sure loading works. 60 | - [[.tst-basic]]: Loading a raw string and validating it. 61 | - [[.tst-load]]: Loading a valid csv file path and validating it. 62 | ``` 63 | 64 | These will allow us to implement testing for SPC-format without having to 65 | create new artifacts. 66 | -------------------------------------------------------------------------------- /book/src/ExampleFile.md: -------------------------------------------------------------------------------- 1 | # REQ-learn 2 | Welcome to the artifact tutorial! This file is written just like artifact 3 | markdown files are. Artifact files can be written in a range of formats, the 4 | currently supported ones being markdown, toml and yaml. 5 | 6 | An artifact file is simply a set of artifacts, each one written like so: 7 | ``` 8 | # REQ-NAME 9 | 10 | ``` 11 | 12 | Artifacts can be a requirement (REQ), design-specification (SPC) 13 | or test (TST) 14 | 15 | The artifact you are reading now is a requirement, therefore it begins with 16 | "REQ". 17 | 18 | 19 | # REQ-markdown 20 | partof: 21 | - REQ-learn 22 | ### 23 | 24 | Artifact files like this one are written in a slightly extended markdown 25 | format. You can read more about markdown here: 26 | http://commonmark.org/help/tutorial/ 27 | 28 | The "extended" part is that artifact treats the following syntax as special: 29 | ``` 30 | # ART-name 31 | 32 | ### 33 | 34 | ``` 35 | 36 | Where `ART` is one of `REQ`, `SPC`, `TST` and `` is 37 | a few items like `partof` and `done` fields. We will get to those later. 38 | 39 | 40 | # SPC-learn 41 | partof: 42 | - REQ-markdown 43 | ### 44 | 45 | Anything starting with SPC is a design specification. 46 | 47 | Requirements (REQ) should be used for: 48 | - Detailing what you want your application to do. 49 | - What the architecture of your application should be. 50 | 51 | Specifications (SPC) should be used for: 52 | - How you intend to write your application (lower level details). 53 | 54 | There are also tests (TST) which we will learn about later. 55 | 56 | 57 | # SPC-partof 58 | partof: 59 | - REQ-learn 60 | ### 61 | 62 | Artifact uses the names of artifacts to automatically link them and track 63 | progress. This makes it easy for the user to intuitively link together 64 | requirements with their specification and reduces boilerplate. 65 | 66 | For instance, `[[SPC-learn]]` is automatically a "partof" `REQ-learn` because 67 | the names after the type are the same ("-learn"). 68 | 69 | You can also explicitly link artifacts like so: 70 | ``` 71 | # SPC-name 72 | partof: 73 | - SPC-other 74 | - 75 | ### 76 | 77 | ``` 78 | 79 | Here is a graph of valid partof relations between artifacts: 80 | ``` 81 | REQ <-- SPC <-- TST 82 | ``` 83 | 84 | In other words: 85 | - A REQ can be partof a REQ only 86 | - A SPC an be partof a REQ or SPC 87 | - A TST can be partof a REQ, SPC or TST 88 | 89 | # SPC-valid 90 | 91 | There are only a few rules for defining artifacts: 92 | - Case is ignored for all names. 93 | - Names cannot overlap, even in different files. 94 | - All names must start with either REQ, SPC or TST. 95 | 96 | 97 | # TST-definition 98 | TST artifacts (and subartifacts) are used to document test design and are the 99 | only way that an artifact can be considered "tested" (besides the `done` 100 | field). 101 | 102 | Artifact makes it easy to track the "progress" of your application because `art 103 | ls` (and the web-ui) gives you easy to easy to read completion and tested 104 | percentages for all your artifacts based on which ones are implemented in 105 | source code (more on that later). 106 | 107 | 108 | # SPC-implementing 109 | Artifacts are implemented by putting links anywhere your source code, i.e. 110 | `#SPC-name`. There are also subartifacts, i.e. `#SPC-name.sub`. 111 | 112 | Subartifacts are defined by putting `[[.subart]]` anywhere in the text. These 113 | artifacts are used to break down how to implement an artifact in pieces which 114 | should then be linked in code. 115 | 116 | Unit tests can be specified by using `[[.tst-name]]`. These kind of subarts 117 | contribute to an artifact's `tst%`. 118 | 119 | -------------------------------------------------------------------------------- /book/src/ExportingHtml.md: -------------------------------------------------------------------------------- 1 | The `art export html $DEST` command can be used to create a static site which 2 | is included on github. For an example, see 3 | [artifact's own design docs](http://vitiral.github.io/artifact/index.html) 4 | 5 | In order to make a github page for your site that hosts your design documents: 6 | - [Activate github pages](https://pages.github.com/) (we will be using the 7 | `index.html` option) 8 | - Run `art export html`, which will generate an `index.html` file among other 9 | necessary files and folders. 10 | - Run `git add index.html css` to add the generated files. 11 | - Push to master or to `gh-pages` branch. 12 | 13 | That's it! You should be able to navigate to 14 | `http://.github.io//` to view your page! 15 | -------------------------------------------------------------------------------- /book/src/FAQ.md: -------------------------------------------------------------------------------- 1 | ## Why is it named artifact? 2 | Artifact is simply named after what it does: it is a way to write and track 3 | your [artifacts](https://en.wikipedia.org/wiki/Artifact_(software_development)) 4 | 5 | ### Why is (extended) markdown the default language? 6 | Because it is human/readable and writeable. Adding the metadata block was also 7 | not difficult and fit within the syntax. 8 | 9 | ### An artifact is "implemented" in code but not 100% done? 10 | All artifacts are only as done as their parts + implementation/done. 11 | 12 | If you have: 13 | ```toml 14 | [SPC-1] 15 | [SPC-1-a] 16 | [SPC-1-b] 17 | ``` 18 | 19 | And then the code: 20 | ```python 21 | def hello(): 22 | """partof: #SPC-1""" 23 | ``` 24 | 25 | `SPC-1` will only be 1/3 "done" since it still has two incomplete parts. 26 | 27 | This also applies to the "done" field. 28 | -------------------------------------------------------------------------------- /book/src/Feedback.md: -------------------------------------------------------------------------------- 1 | # Reporting an Issue 2 | 3 | If you have any issues with artifact, please report a bug at it's [issue 4 | tracker][0]. 5 | 6 | # Feedback on Artifact 7 | 8 | Below is feedback I have compiled on artifact so far. If you would like to 9 | leave feedback please [open a ticket][0], contact me on twitter 10 | [@vitiral](https://twitter.com/vitiral) or 11 | [on reddit](https://www.reddit.com/user/vitiral). 12 | 13 | - [omniaVincitVeritas, June 2017][1]: I like this idea a lot. Our profession 14 | has a real problem with massively overengineered architecture tools, but 15 | artifact is like fresh summer rain. 16 | 17 | [0]: https://github.com/vitiral/artifact/issues 18 | [1]: https://www.reddit.com/r/rust/comments/6lhnbp/artifact_081_released_finalfinal_beta/djv60xp/ 19 | -------------------------------------------------------------------------------- /book/src/Finishing.md: -------------------------------------------------------------------------------- 1 | # Finishing The Project 2 | 3 | This is a continuation of the last section and is still a work in progress. We 4 | are going to flush out the design for the rest of the flash challenge and 5 | implement an MVP. 6 | -------------------------------------------------------------------------------- /book/src/GettingStarted.md: -------------------------------------------------------------------------------- 1 | # InteractiveTutorial 2 | -------------------------------------------------------------------------------- /book/src/Installation.md: -------------------------------------------------------------------------------- 1 | This is the installation guide. For more information see the 2 | [project home page][1] 3 | 4 | ## Typical Installation 5 | artifact is compiled for linux, mac and windows. You can find releases on the 6 | **[github release page](https://github.com/vitiral/artifact/releases)**. 7 | 8 | For Linux and Mac, simply download and unpack the tarball with 9 | `tar -zxvf .tar.gz`. Then put it somewhere in your [PATH][10] 10 | 11 | [10]: http://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path 12 | 13 | ### Windows 14 | 15 | The recommended method of installation for windows is to use the **scoop** 16 | package manager. 17 | 18 | First, [install scoop](http://scoop.sh/) from a powershell terminal: 19 | ``` 20 | iex (new-object net.webclient).downloadstring('https://get.scoop.sh') 21 | ``` 22 | 23 | Then install artifact: 24 | ``` 25 | scoop install artifact 26 | ``` 27 | 28 | ### Arch Linux 29 | In addition to the installation methods above, Artifact is maintained as a 30 | package on the Arch AUR by [@rubdos][4]: 31 | 32 | https://aur.archlinux.org/packages/artifact/ 33 | 34 | ## Building From Source 35 | Simply execute the following: 36 | ```bash 37 | git clone https://github.com/vitiral/artifact 38 | cd artifact 39 | cargo build --release 40 | ``` 41 | 42 | > Note: you may need `cargo-web` installed as well. 43 | 44 | Do a full suite of tests with: 45 | ```bash 46 | cargo test 47 | ``` 48 | 49 | ## Installing with [cargo](https://github.com/rust-lang/cargo) 50 | 51 | Install rust with [rustup](https://github.com/rust-lang-nursery/rustup.rs) and 52 | type `cargo install artifact-app` 53 | 54 | Note this may never be feature complete and is not the recommended method of 55 | installation. 56 | 57 | [1]: https://github.com/vitiral/artifact 58 | [2]: https://github.com/vitiral/artifact/blob/master/docs/ExportingHtml.md 59 | [3]: https://github.com/vitiral/artifact/tree/server 60 | [4]: https://github.com/rubdos 61 | -------------------------------------------------------------------------------- /book/src/Introduction.md: -------------------------------------------------------------------------------- 1 | # Artifact Introduction 2 | 3 | Welcome to the Artifact Tutorial and Simple Quality Leaflet! 4 | 5 | This "book" (it is a very small book) also serves as the tutorial for 6 | [artifact][artifact], the design documentation tool made for everybody 7 | (including developers!). You can get this book on the project's home 8 | design documents (**TODO: add link**) and it also ships with the Web UI of 9 | every artifact (just follow the **docs** in the header). 10 | 11 | Artifact is a simple, linkable and trackable design documentation tool for 12 | everybody. It allows anyone to write and link their design documents both to 13 | each other and to source code, making it easy to know how complete their 14 | project is. Documents are revision controllable, can be edited in the browser 15 | and have a full suite of command line tools for searching, displaying, 16 | checking, exporting and formatting them. 17 | 18 | This book is broken into 3 main sections: 19 | - Artifact introduction: introducing you to the syntax and basic philosophy of 20 | artifact. 21 | - Simple Quality: an interactive guide for achieving high quality with minimal 22 | effort geared more towards beginner to intermediate software developers. 23 | - Addendum: complete list of features, fullpage specification, etc. 24 | 25 | [artifact]: https://github.com/vitiral/artifact 26 | -------------------------------------------------------------------------------- /book/src/License.md: -------------------------------------------------------------------------------- 1 | # Artifact Documentation Directory License 2 | 3 | All documents in this directory are released under the CC0 Creative Commons 4 | Public Domain License with the intent that you should feel free to copy, paste 5 | and modify any of the designs, guides or examples for any purpose. You can read 6 | more about CC0 here: 7 | 8 | [https://creativecommons.org/publicdomain/](https://creativecommons.org/publicdomain/) 9 | -------------------------------------------------------------------------------- /book/src/Purpose.md: -------------------------------------------------------------------------------- 1 | # Specifying Your Purpose 2 | 3 | One of the most critical pieces of documentation is your purpose documentation. 4 | Without purpose documentation, it is easy to get lost and forget what your 5 | project was trying to accomplish. 6 | 7 | We are going to start by writing our requirements in our `README.md`. Later we 8 | are going to use artifact to track them. 9 | 10 | Open up your `README.md` in your favorite plain-text editor and write out 11 | something like the following: 12 | 13 | ```markdown 14 | # Purpose: 15 | Write a flash card quizzer from scratch and learn about 16 | quality best practices while doing so. 17 | 18 | The example tutorial can be found here: 19 | http://wiki.openhatch.org/Flash_card_challenge 20 | 21 | It should be easy for users to input questions to the 22 | quizzer in a simple and open format. Additionally, the 23 | quizzer should use effective memorization techniques. 24 | Some possible ideas include: 25 | - asking items in a random order 26 | - telling the correct answer after the user answers incorrectly 27 | - asking items more often if they were answered incorrectly 28 | - allowing users to configure time limits, so they can 29 | compare results between quizzes. 30 | ``` 31 | 32 | Notice that we try to keep our purpose documentation as brief and simple as 33 | possible. This is important for all documents, but is especially important for 34 | high level docs. There is a basic rule: documentation that is not brief and 35 | clear will not be read. You want to keep your docs readable, otherwise they 36 | will only weigh down your project. 37 | 38 | > ##### Exercise 1: 39 | > In your `README.md`, break down the purpose documentation above into some high 40 | > level requirements. Then give a high level specification for how you would 41 | > approach those requirements. What programming language would you use? What 42 | > libraries would you use? What would be your overall approach to each problem? 43 | 44 | > ##### Exercise 2: 45 | > Assume your program user interface would be over the command line. What kind 46 | > of arguments and user configuration would you accept? Would you let the user 47 | > use only one quiz file at a time, or use multiple of them? Write down your 48 | > answers. 49 | 50 | > ##### Exercise 3: 51 | > Skim through the [markdown format][1] specification. Markdown is a great 52 | > format for keeping docs, since it allows you to write docs in plain text 53 | > (so they can be revision controlled) but the simple formatting rules 54 | > render beautifully on sites like github. 55 | > 56 | > Markdown is easy to learn, easy to read and has become the defacto standard 57 | > for writing docs for open source projects. It is worth learning! 58 | 59 | [1]: https://gitbookio.gitbooks.io/markdown/content/ 60 | -------------------------------------------------------------------------------- /book/src/PurposeArtifact.md: -------------------------------------------------------------------------------- 1 | # Purpose in Artifact 2 | -------------------------------------------------------------------------------- /book/src/RunningTests.md: -------------------------------------------------------------------------------- 1 | # Running Tests 2 | 3 | If you followed along with the artifact interactive tutorial, you should feel 4 | pretty confident by now that our load component is well designed and *should* 5 | be implemented and tested. However, you haven't actually run any code yet, so 6 | you can't be sure! We are going to change that. 7 | 8 | The first thing you need to do is make sure you are running python2.7. Running: 9 | ``` 10 | python --version 11 | pip --version 12 | ``` 13 | 14 | Should return something like: 15 | ``` 16 | Python 2.7.13 17 | pip 9.0.1 from /usr/lib/python2.7/site-packages (python 2.7) 18 | ``` 19 | 20 | As long as they are both python2.7.X (but not python3.X), you are good to go. 21 | 22 | > If not... python can be very difficult to configure. Search on google for 23 | > how to have both python2 and python3 installed. You will have to do a similar 24 | > exercise for `pip`. 25 | 26 | > If it is too much of a pain, you can also just use python3 (or any other 27 | > language), it shouldn't be difficult -- you will just have to fix any errors 28 | > that come up. 29 | > 30 | > If you are using another language, refer to that language's unit testing 31 | > guide. 32 | 33 | Now install `py.test`: 34 | ``` 35 | pip install pytest 36 | ``` 37 | > Note: it is recommended you add `--user` to the end or use a virtualenv. 38 | > Using a virtualenv with python is out of scope of this tutorial. 39 | 40 | Now run your unit tests: 41 | ``` 42 | py.test flash/ 43 | ``` 44 | 45 | Congratulations, you've designed, written and run unit tests! 46 | 47 | -------------------------------------------------------------------------------- /book/src/SPECIFICATION.md: -------------------------------------------------------------------------------- 1 | # Artifact Document Specification 2 | 3 | This document outlines the specification for the Artifact data format. 4 | All specifications in this document are released as Creative Commons CC0 5 | public domain. You can read more about this license here: 6 | https://creativecommons.org/publicdomain/ 7 | 8 | ## Document Type 9 | 10 | Artifact documents can be specified in multiple formats. 11 | 12 | ### TOML Format 13 | The TOML format adheres to a subset of the [TOML][1] format and are documents 14 | of the form: 15 | 16 | ```toml 17 | [ART-baz] 18 | partof = "ART-baa" 19 | text = ''' 20 | multi-line 21 | description 22 | ''' 23 | 24 | [ART-foo-bar] 25 | partof = [ 26 | "ART-baz", 27 | ] 28 | text = ''' 29 | multi-line 30 | description 31 | ''' 32 | ``` 33 | 34 | Where `partof` can be either a single string or a list of strings. 35 | 36 | ### Markdown Format 37 | The markdown format uses extended Commonmark (**TODO: link**) format. 38 | It is of the form: 39 | 40 | ``` 41 | # REQ-foo 42 | 43 | ### 44 | 45 | ``` 46 | 47 | Where the yaml section is completely optional (the `###` can be skipped if it 48 | doesn't need it. 49 | 50 | ## Artifact Types 51 | 52 | Instead of `ART` as defined in Document Type, the user must select from 53 | 3 artifact types: 54 | - `REQ`: specifying a requirement. `REQ` can only have `REQ` in its 55 | `partof` field. 56 | - `SPC`: specifying a design specification. `SPC` can only have 57 | `REQ` or `SPC` in its `partof` field. 58 | - `TST`: specifying a test of a `SPC`. `TST` can have any of 59 | `REQ`, `SPC` or `TST` in its `partof` field. 60 | 61 | ## Automatic Links 62 | 63 | The following will be automatically linked: 64 | - parents: `REQ-foo` will automatically be a `partof` 65 | `REQ-foo-bar` 66 | - common-prefix for `REQ -> SPC -> TST` links 67 | - `REQ-foo` will automatically be a `partof` `SPC-foo` 68 | *if `REQ-foo` exists* 69 | - `SPC-foo` will automatically be a `partof` `TST-foo` 70 | *if `SPC-foo` exists* 71 | 72 | ## Linking an artifact in source code 73 | Artifacts can be linked in source code, which "completes" their `spc%`. 74 | 75 | The way to link to an artifact is to place `#ART-name` anywhere in the source 76 | code file. 77 | 78 | ## Sub Artifacts (subart) 79 | A sub artifact is defined by placing `[[.subart]]` anywhere in the `text` field 80 | of an artifact. 81 | 82 | Subarts can be linked in source code as well by placing `#ART-name.subart` 83 | anywhere in the source code file. 84 | 85 | A special subart is `[[.tst-subart]]` which will contribute to both `tst%` and 86 | `spc%`. 87 | 88 | 89 | [1]: https://github.com/toml-lang/toml 90 | -------------------------------------------------------------------------------- /book/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Introduction](./Introduction.md) 4 | - [Installation](./Installation.md) 5 | - [Cheat Sheet](./CheatSheet.md) 6 | - [Example](./ExampleFile.md) 7 | 8 | - [Simple Quality with Artifact](./SimpleQuality.md) 9 | - [Starting Your Project](./StartingProject.md) 10 | - [Specifying Your Purpose](./Purpose.md) 11 | - [High Level Design](./Design.md) 12 | - [Vocabulary](./Vocabulary.md) 13 | - [Tools](./Tools.md) 14 | - [Artifact Intro](./ArtifactIntro.md) 15 | - [Detailed Design](./DetailedDesign.md) 16 | - [Implementation](./Implementation.md) 17 | - [Cleaning Up](./CleaningUp.md) 18 | 19 | - [Finishing The Project](Finishing.md) 20 | - [Running Tests](./RunningTests.md) 21 | - [TODO](./TODO.md) 22 | 23 | - [Addendum](./Addendum.md) 24 | - [FAQ](./FAQ.md) 25 | - [Best Practices](./BestPractices.md) 26 | - [Exporting Html](./ExportingHtml.md) 27 | - [Feedback](./Feedback.md) 28 | - [Specification](./SPECIFICATION.md) 29 | - [License](./License.md) 30 | -------------------------------------------------------------------------------- /book/src/SimpleQuality.md: -------------------------------------------------------------------------------- 1 | # Simple Quality 2 | *A short guide to quality best practices for developers.* 3 | 4 | By Garrett Berg 5 | 6 | ## Introduction 7 | This is a short and open-source leaflet aimed at helping software developers 8 | improve their software quality. It is also the primary user guide for the design 9 | documentation tool [artifact][4]. Its targeted audience are those who: 10 | - Know at least one programming language. 11 | - Know revision control. If you don't know one, learn git. 12 | - Want a brief guide on how to have fewer bugs, re-designs and headaches 13 | in all of their projects. 14 | 15 | This book is shiped as part of the artifact Web UI and can also be read at 16 | (**TODO: add link**). 17 | 18 | If you have suggestions or edits, please [open a ticket](./Feedback.html). 19 | 20 | The goal of this book is to make developing software simpler and more fun. Think 21 | back to the time you first learned revision control. Think about how you were 22 | backing up files before then? Maybe you were copying folders to some `backups` 23 | folder? Maybe you were not backing up at all? 24 | 25 | However you did (or didn't) track your changes, think about your life before and after 26 | revision control. Things were a lot different, and all you had to learn in order 27 | to use revision control were: 28 | - Some simple vocabulary. 29 | - An easy to use tool. 30 | - A new way of looking at things. 31 | 32 | This is the central premise of this book: you don't need to understand technical 33 | jargon or complex test methodologies to realize huge gains in the quality of 34 | your software. Some simple vocabulary, new tools and new ways of looking at 35 | things are all you need. 36 | 37 | > All code/documentation examples in this book are public domain. For more 38 | > information see the [License](./License.html) 39 | 40 | [2]: https://github.com/vitiral/simple-quality/issues 41 | [3]: https://www.google.com/search?q=gnu+gpl+v3&ie=utf-8&oe=utf-8 42 | [4]: https://github.com/vitiral 43 | 44 | 45 | ## Why This Book Exists 46 | There is a lack of good documentation unifying and extending quality best 47 | practices. While there have been several advancements made in how to develop 48 | quality software, they have largely been piecemeal and lacked the tools to 49 | fit them all together. Several of the recent advancements include: 50 | - better revision control tools and best practices 51 | - new emphasis on unit tests as part of the development process 52 | - linters and auto-formatters to help projects have easy to read code 53 | - more emphasis on documentation, including inline developer documentation 54 | - the agile process and associated tools 55 | 56 | One of the things in common about all of these: developers tend to agree 57 | that their lives are **better** after using them. Programming is easier, 58 | more fun and more fulfilling. However, all of these lack the processes, 59 | tools and vocabulary necessary to bring them together into an organized whole. 60 | 61 | This book will give you the knowledge of how to unify and track all these quality 62 | best practices as well as give you an intro to artifact, the open-source documentation 63 | tool artifact. The tools presented in this book will not only allow you to write 64 | better software, but will help your day-to-day workflow in the same ways that 65 | good unit tests do. 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /book/src/StartingProject.md: -------------------------------------------------------------------------------- 1 | # Starting Your Project 2 | 3 | The primary teaching method that this book will employ is "learning by doing". 4 | This is an approach that many developers are familiar with and is used in some 5 | of the most effective tutorials on software development. 6 | 7 | The project we will be implementing is the [flash card challenge][2] created 8 | by Open Hatch. There are several reasons this project was chosen: 9 | - It has a clear goal with targeted users. 10 | - It is simple to define and yet can be extremely broad. 11 | - The guide is written in python which largely reads like pseudo code. 12 | You should be able to follow along in any language. 13 | 14 | One of the best tutorials on C (in my opinion), [learn C the hard way][3] has 15 | this to say about itself: 16 | 17 | > [This tutorial] teaches real robust C coding and defensive programming 18 | > tactics on real hardware rather than abstract machines and pedantic theory. 19 | > The book emphasizes breaking your code on purpose, and in the process teaches 20 | > a plethora of important topics. 21 | 22 | There are three important aspects to the "Learn The Hard Way" method that 23 | this tutorial will use: 24 | 1. It is designed for absolute beginners: you should know the basics of a 25 | programming language and revision control, but that's all you need. 26 | 2. It focuses on teaching simple concepts and tools which deliver immediate 27 | real-world value. 28 | 3. It uses exercises as the primary teaching method. You must 29 | **actually do the excersies** if you want to understand how the tools and 30 | processes you are reading about are useful. 31 | 32 | ## Before we start 33 | 34 | Before we start, install the following tools: 35 | - [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) 36 | - [artifact](https://github.com/vitiral/artifact/blob/master/docs/Installation.md) 37 | 38 | Now run the following: 39 | ``` 40 | mkdir ~/learn-art # or whatever directory you want 41 | cd ~/learn-art 42 | git init 43 | art init 44 | ``` 45 | 46 | This will set up your project as an artifact tutorial project and initialize 47 | git. It is your job to know how to use git as we progress through the 48 | tutorial. I recommend committing the files you have now, including the `.art/` 49 | directory that was created. 50 | 51 | > ##### Exercise 1: 52 | > Create a `README.md` file in this directory and take notes while you read the 53 | > [flash card challenge][2] webpage. Pay close attention to: 54 | > - what is the use case (how will this software be used)? 55 | > - what are the inputs/outputs of the program? 56 | > 57 | > Then write a paragraph answering the question "how would I develop 58 | > this application, knowing only what I know now?" 59 | 60 | [1]: https://github.com/vitiral/artifact 61 | [2]: http://wiki.openhatch.org/Flash_card_challenge 62 | [3]: https://learncodethehardway.org/c/ 63 | 64 | -------------------------------------------------------------------------------- /book/src/TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | The rest of these documents are not yet complete. Sorry for the inconvieneice! 4 | 5 | -------------------------------------------------------------------------------- /book/src/WebUi.md: -------------------------------------------------------------------------------- 1 | # Artifact Web UI 2 | 3 | For an example web ui, see [artifact's own design docs][2] 4 | 5 | The artifact Web UI is intended to be simple and intuitive, however 6 | it can be helpful to have some context. 7 | 8 | For more information about artifact, see it's [homepage][1] 9 | 10 | [1]: https://github.com/vitiral/artifact 11 | [2]: http://vitiral.github.io/artifact/#artifacts/req-1 12 | 13 | ## Artifact Color 14 | 15 | An "artifact" is something with a name like "ART-name" where "ART" is 16 | one of: 17 | - `REQ`: a requirement 18 | - `SPC`: a design specification 19 | - `TST`: a test 20 | 21 | Artifacts can take on different colors representing: 22 | - green: artifact is completed and tested 23 | - blue: artifact is completed but not tested (or partially complete and tested) 24 | - yellow: artifact is somewhat complete/tested 25 | - red: artifact is not very complete or tested 26 | 27 | ## List View 28 | 29 | The base view is the List View. It contains a column selector at the top 30 | left, a search bar at the top right, and a list of the searched artifacts 31 | below. 32 | 33 | ### Column Selector 34 | The column selector lets you select columns you wish to view. Displayed 35 | columns will be black and hidden columns will be grey. 36 | 37 | ### Search Bar 38 | The search bar allows you to search in the `name`, `parts`, `partof` and/or 39 | `text` fields for the value in the search bar. By default it searches for 40 | (case insensitive) text, but you can also enable regex searching with the 41 | button to the right of the search bar. 42 | -------------------------------------------------------------------------------- /book/src/data/artifact-thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/artifact-thumb.png -------------------------------------------------------------------------------- /book/src/data/attribution/Attribution.md: -------------------------------------------------------------------------------- 1 | # Attribution for files in this folder 2 | - [b0rk-design-documents.jpg-large](https://twitter.com/b0rk/status/833419052194357248): twitter @b0rk 3 | -------------------------------------------------------------------------------- /book/src/data/attribution/b0rk-design-documents.jpg-large: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/attribution/b0rk-design-documents.jpg-large -------------------------------------------------------------------------------- /book/src/data/example-hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/example-hello.png -------------------------------------------------------------------------------- /book/src/data/quickstart/images.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/images.xcf -------------------------------------------------------------------------------- /book/src/data/quickstart/text-REQ-purpose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/text-REQ-purpose.png -------------------------------------------------------------------------------- /book/src/data/quickstart/text-req-parts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/text-req-parts.png -------------------------------------------------------------------------------- /book/src/data/quickstart/web-create-btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/web-create-btn.png -------------------------------------------------------------------------------- /book/src/data/quickstart/web-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/web-create.png -------------------------------------------------------------------------------- /book/src/data/quickstart/web-edit-btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/web-edit-btn.png -------------------------------------------------------------------------------- /book/src/data/quickstart/web-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/web-edit.png -------------------------------------------------------------------------------- /book/src/data/quickstart/web-implemented-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/web-implemented-link.png -------------------------------------------------------------------------------- /book/src/data/quickstart/web-save-btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/web-save-btn.png -------------------------------------------------------------------------------- /book/src/data/quickstart/web-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/web-select.png -------------------------------------------------------------------------------- /book/src/data/quickstart/web-source-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/web-source-code.png -------------------------------------------------------------------------------- /book/src/data/quickstart/web-spc-world-done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/quickstart/web-spc-world-done.png -------------------------------------------------------------------------------- /book/src/data/web-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/data/web-ui.png -------------------------------------------------------------------------------- /book/src/examples/part1/artifact-frontend.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/examples/part1/artifact-frontend.wasm -------------------------------------------------------------------------------- /book/src/examples/part1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Artifacts 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /book/src/examples/part1/initial.json: -------------------------------------------------------------------------------- 1 | {"project":{"paths":{"base":"/home/garrett/tmp/learn-art","code_paths":[],"exclude_code_paths":[],"artifact_paths":["/home/garrett/tmp/learn-art/design"],"exclude_artifact_paths":[]},"code_impls":{},"artifacts":{"REQ-purpose":{"id":"DoWdPsuX4839k2qxuZTMvA","name":"REQ-purpose","file":"/home/garrett/tmp/learn-art/design/purpose.md","partof":[],"parts":["SPC-cli","SPC-format","SPC-report"],"completed":{"spc":0.0,"tst":0.0},"text":"Write a flash card quizzer from scratch and learn about\nquality best practices while doing so.\n\nThe example tutorial can be found here:\n http://wiki.openhatch.org/Flash_card_challenge\n\nIt should be easy for users to input questions to the\nquizzer in a simple and open format. Additionally, the\nquizzer should use effective memorization techniques.\nSome possible ideas include:\n- asking items in a random order\n- telling the correct answer after the user answers incorrectly\n- asking items more often if they were answered incorrectly\n- allowing users to configure time limits, so they can\n compare results between quizzes.\n","impl_":{"type":"NotImpl"},"subnames":[]},"SPC-cli":{"id":"dbuUzJ9Wq49iD2zxFn9NpA","name":"SPC-cli","file":"/home/garrett/tmp/learn-art/design/purpose.md","partof":["REQ-purpose"],"parts":[],"completed":{"spc":0.0,"tst":0.0},"text":"\nThe minimum viable product shall be a command line utility\nthat is given the path to one or more question files as\narguments\n\nAdditional arguments will include:\n- `-t`: specify the time allowed for each question\n- `-T`: specify the total time allowed for the whole quiz\n- `-r NUM`: repeat questions only a certain number of times.\n By default there is no limit\n\nThe program will ask one question at a time, recording how\nmany answers the user got correct/incorrect and weighting\nfuture questions accordingly.\n\nWhen the program is complete it will report:\n- time taken, broken up by whole quiz and each question\n- the user's score\n","impl_":{"type":"NotImpl"},"subnames":[]},"SPC-format":{"id":"VM5AuyTYowZV6azM2wSdgA","name":"SPC-format","file":"/home/garrett/tmp/learn-art/design/purpose.md","partof":["REQ-purpose"],"parts":[],"completed":{"spc":0.0,"tst":0.0},"text":"The user shall be able to easily configure the quiz\nquestions through a simple csv format consisting of two\ncolumns: the question and the answer.\n","impl_":{"type":"NotImpl"},"subnames":[]},"SPC-report":{"id":"dhK_a1g7CMdYnKbRzVCwaw","name":"SPC-report","file":"/home/garrett/tmp/learn-art/design/purpose.md","partof":["REQ-purpose"],"parts":[],"completed":{"spc":0.0,"tst":0.0},"text":"When the program is complete a report shall be printed with:\n- time taken, broken up by whole quiz and each question\n- the user's total score\n- questions ranked by ones the user had the most difficulty\n","impl_":{"type":"NotImpl"},"subnames":[]}}},"web_type":"Static"} -------------------------------------------------------------------------------- /book/src/examples/part2/artifact-frontend.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/examples/part2/artifact-frontend.wasm -------------------------------------------------------------------------------- /book/src/examples/part2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Artifacts 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /book/src/logo/logo-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/logo/logo-logo.png -------------------------------------------------------------------------------- /book/src/logo/logo-medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/logo/logo-medium.png -------------------------------------------------------------------------------- /book/src/logo/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/logo/logo-small.png -------------------------------------------------------------------------------- /book/src/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/book/src/logo/logo.png -------------------------------------------------------------------------------- /ci/before_deploy.ps1: -------------------------------------------------------------------------------- 1 | # This script takes care of packaging the build artifacts that will go in the 2 | # release zipfile 3 | 4 | $SRC_DIR = $PWD.Path 5 | $STAGE = [System.Guid]::NewGuid().ToString() 6 | 7 | Set-Location $ENV:Temp 8 | New-Item -Type Directory -Name $STAGE 9 | Set-Location $STAGE 10 | 11 | $ZIP = "$SRC_DIR\$($Env:CRATE_NAME)-$($Env:APPVEYOR_REPO_TAG_NAME)-$($Env:TARGET).zip" 12 | 13 | # TODO Update this to package the right artifacts 14 | Copy-Item "$SRC_DIR\target\$($Env:TARGET)\release\hello.exe" '.\' 15 | 16 | 7z a "$ZIP" * 17 | 18 | Push-AppveyorArtifact "$ZIP" 19 | 20 | Remove-Item *.* -Force 21 | Set-Location .. 22 | Remove-Item $STAGE 23 | Set-Location $SRC_DIR 24 | -------------------------------------------------------------------------------- /ci/before_deploy.sh: -------------------------------------------------------------------------------- 1 | # This script takes care of building your crate and packaging it for release 2 | 3 | set -ex 4 | 5 | main() { 6 | local src=$(pwd) \ 7 | stage= 8 | 9 | case $TRAVIS_OS_NAME in 10 | linux) 11 | stage=$(mktemp -d) 12 | ;; 13 | osx) 14 | stage=$(mktemp -d -t tmp) 15 | ;; 16 | esac 17 | 18 | test -f Cargo.lock || cargo generate-lockfile 19 | 20 | # $BTOOL rustc --bin art --target $TARGET --release -- -C lto 21 | $BTOOL build -p artifact-app --target $TARGET --release 22 | 23 | cp target/$TARGET/release/art $stage/ 24 | 25 | cd $stage 26 | tar czf $src/${RELEASE_NAME}.tar.gz * 27 | cd $src 28 | ls -al 29 | 30 | rm -rf $stage 31 | } 32 | 33 | main 34 | -------------------------------------------------------------------------------- /ci/data/artifact-thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/ci/data/artifact-thumb.png -------------------------------------------------------------------------------- /ci/data/attribution/Attribution.md: -------------------------------------------------------------------------------- 1 | # Attribution for files in this folder 2 | - [b0rk-design-documents.jpg-large](https://twitter.com/b0rk/status/833419052194357248): twitter @b0rk 3 | -------------------------------------------------------------------------------- /ci/data/attribution/b0rk-design-documents.jpg-large: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/ci/data/attribution/b0rk-design-documents.jpg-large -------------------------------------------------------------------------------- /ci/data/logo/logo-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/ci/data/logo/logo-logo.png -------------------------------------------------------------------------------- /ci/data/logo/logo-medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/ci/data/logo/logo-medium.png -------------------------------------------------------------------------------- /ci/data/logo/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/ci/data/logo/logo-small.png -------------------------------------------------------------------------------- /ci/data/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/ci/data/logo/logo.png -------------------------------------------------------------------------------- /ci/install.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | install_cross() { 4 | local target= 5 | if [ $TRAVIS_OS_NAME = linux ]; then 6 | target=x86_64-unknown-linux-musl 7 | sort=sort 8 | else 9 | target=x86_64-apple-darwin 10 | sort=gsort # for `sort --sort-version`, from brew's coreutils. 11 | fi 12 | 13 | # Builds for iOS are done on OSX, but require the specific target to be 14 | # installed. 15 | case $TARGET in 16 | aarch64-apple-ios) 17 | rustup target install aarch64-apple-ios 18 | ;; 19 | armv7-apple-ios) 20 | rustup target install armv7-apple-ios 21 | ;; 22 | armv7s-apple-ios) 23 | rustup target install armv7s-apple-ios 24 | ;; 25 | i386-apple-ios) 26 | rustup target install i386-apple-ios 27 | ;; 28 | x86_64-apple-ios) 29 | rustup target install x86_64-apple-ios 30 | ;; 31 | esac 32 | 33 | # This fetches latest stable release 34 | local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \ 35 | | cut -d/ -f3 \ 36 | | grep -E '^v[0.1.0-9.]+$' \ 37 | | $sort --version-sort \ 38 | | tail -n1) 39 | curl -LSfs https://japaric.github.io/trust/install.sh | \ 40 | sh -s -- \ 41 | --force \ 42 | --git japaric/cross \ 43 | --tag $tag \ 44 | --target $target 45 | } 46 | 47 | main() { 48 | # install_cross 49 | 50 | # TODO: remove this 51 | # give windows a place to put the book 52 | mkdir -p ./book/out/book 53 | 54 | cargo install cargo-web --debug || echo "cargo-web already installed" 55 | cargo install mdbook --debug || echo "mdbook already installed" 56 | # mkdir -p target/deps 57 | 58 | # cp `which cargo-web` target/deps 59 | # cp `which mdbook` target/deps 60 | # ls -al target/deps 61 | } 62 | 63 | main 64 | -------------------------------------------------------------------------------- /ci/script.sh: -------------------------------------------------------------------------------- 1 | # This script takes care of testing your crate 2 | 3 | set -ex 4 | 5 | main() { 6 | # must be done first 7 | cargo-web deploy -p artifact-frontend --release --target=wasm32-unknown-unknown 8 | $BTOOL build -p artifact-app --target $TARGET 9 | 10 | if [ ! -z $DISABLE_TESTS ]; then 11 | return 12 | fi 13 | 14 | $BTOOL test -p artifact-app --target $TARGET 15 | 16 | $BTOOL run -p artifact-app --target $TARGET -- help 17 | } 18 | 19 | # we don't run the "test phase" when doing deploys 20 | if [ -z $TRAVIS_TAG ]; then 21 | main 22 | fi 23 | -------------------------------------------------------------------------------- /design/cli.md: -------------------------------------------------------------------------------- 1 | # SPC-cli 2 | partof: REQ-purpose 3 | ### 4 | 5 | The CLI is the primary developer interatction with artifact, alongside the Web 6 | UI for visualizing the artifacts. The main goal of the CLI is to provide the 7 | tools that every developer is used to in a typical development tool. This 8 | includes: 9 | 10 | 11 | - [[.init]]: Initialize a project for using artifact. This is pretty basic, just need 12 | a `.art` folder with a `settings.toml` and an initial `design/` folder. 13 | - [[.check]]: checking for errors AND warnings with a return code if there is an error. 14 | - If there are only warnings the return code == 2. Otherwise it == 1. 15 | - [[.fmt]]: auto format the project. 16 | - `--type` flag to change the filetype. 17 | - [[SPC-cli-ls]]: listing/searching for artifacts, see the full specification. 18 | - [[.serve]]: the command to start the web backend. 19 | 20 | 21 | All subcommands should include the following flags: 22 | - `-v / --verbose` for setting the logging verbosity. 23 | - `--work-dir` for setting the working directory to run the command out of. 24 | 25 | 26 | # SPC-cli-ls 27 | The `art ls` command shall be used to list information about the artifacts in a 28 | project. 29 | 30 | `ls` is the primary window into a user's artifacts, creating a simple interface 31 | to glimpse large amounts of information. 32 | 33 | ## [[.args]]: Arguments 34 | `art ls` with no commands will simply print all artifacts with standard 35 | settings, each on a single line. 36 | 37 | The args are as follows: 38 | - `SEARCH str`: positional argument detailing which artifacts to display 39 | By default, this will be interpreted as an Artifact Name and can therefore 40 | only display one artifact. However, if pattern searching is selected, it 41 | will be interpreted as a rust regexp 42 | - `display`: flags that control what information will be displayed 43 | - `pattern`: searh SEARCH with a regex pattern. The flag specifies which fields 44 | should be searched. 45 | - `completed/tested`: flags which control what percentage completed/tested to 46 | display 47 | - [[.long]]: the `-l` flag prints the artifact in "long" form. Without it it 48 | is printed in [[.table]] form. 49 | 50 | ## [[.color]]: Color 51 | In order to make viewing of information via cmdline easier, artifact **shall** 52 | colorize it's output to make it clear which items are done or not done or in 53 | error. 54 | 55 | The following are the general rules: 56 | - Names that are complete will be `green`. 57 | - Names that are almost complete will be `blue`. 58 | - Names that are somewhat complete will be `yellow`. 59 | - Names that are very litle or not complete will be `red`. 60 | - Names that are in ERROR will be `bold red`. 61 | 62 | For [[.color_spc]], the levels are: 63 | - `( 100%, 70%, 40%, 0%)`: percentage spc 64 | - `( 3, 2, 1, 0)`: points 65 | - `(green, blue, yellow, red)`: colors 66 | 67 | For [[.color_tst]], the levels are: 68 | - `( 100%, 50%, 0%)`: percentage tst 69 | - `( 2, 1, 0)`: points 70 | - `(green, yellow, red)`: colors for tst 71 | 72 | For [[.color_name]] you add the two points together: 73 | - 5: Name is Green 74 | - 3-4: name is blue 75 | - 1-2: name is yellow 76 | - 0: name is red -------------------------------------------------------------------------------- /design/data/cache.md: -------------------------------------------------------------------------------- 1 | # SPC-read-cache 2 | > This specification only exists to improve performance 3 | 4 | Significant speed gains can be made by caching artifact data into a local 5 | SQLite database in `.art/db.sql`. For linux specifically (and probably MacOS, 6 | don't know about windows) you can get the timestamp when any file was modified. 7 | 8 | - If we only parsed files where the timestamp changed we could speed things up 9 | significantly for just querying their results from an sql database. This is 10 | especially true for files that don't have *any* links. -------------------------------------------------------------------------------- /design/data/family.md: -------------------------------------------------------------------------------- 1 | # SPC-family 2 | partof: REQ-data 3 | ### 4 | An artifact (name) has the following "family" defined: 5 | 6 | ```dot 7 | digraph G { 8 | subgraph cluster_allowed { 9 | label=<allowed partof>; 10 | REQ -> SPC -> TST; 11 | REQ -> TST; 12 | 13 | REQ -> REQ; 14 | SPC -> SPC; 15 | TST -> TST; 16 | } 17 | 18 | subgraph cluster_relationship { 19 | label=<auto family>; 20 | "REQ-root" 21 | -> {"REQ-root-child" [color=blue]} 22 | [label="is parent of"; color=blue; fontcolor=blue]; 23 | "REQ-root" -> "SPC-root" [label="is auto-partof"]; 24 | "SPC-root" 25 | -> {"SPC-root-child" [color=blue]} 26 | [label="is parent of"; color=blue; fontcolor=blue]; 27 | "SPC-root" -> "TST-root" [label="is auto-partof"]; 28 | } 29 | } 30 | ``` 31 | 32 | ## Allowed Partof 33 | The first graph shows what relationships are "allowed". It specifies that: 34 | - `REQ` can be `partof` any type 35 | - `SPC` can be `partof` `SPC` and `TST` 36 | - `TST` can only be `partof` itself. 37 | 38 | In essense: 39 | - You can always create "subtypes", i.e. a more specific requirement 40 | - You can create a specification that is "partof" a requirement. This makes 41 | sense as you want to define your specifications based on your requirements. 42 | - You can create a test that is "partof" a specification OR a requirement. 43 | For example, white box testing will be based on a specification whereas 44 | blackbox ("requirements based") testing will be based on a requirement. 45 | 46 | ## Lints 47 | Lints are required to make sure the above is upheld 48 | 49 | - [[.lint_partof_exists]]: Make sure any partof references actually exist. 50 | - [[.lint_types]]: Make sure that `partof` links are only made between valid types. 51 | 52 | ## [[.auto]]: Auto Relationships 53 | The second graph shows the "automatic relationships" of nodes to their 54 | parents. 55 | 56 | - A node is automatically a `partof` both its parent and it's auto-partof. 57 | - Artifacts that have only one element are "root" (i.e. REQ-root, REQ-foo, SPC-foo) 58 | - Any artifact that is *not* root has a single parent, which it will automatically 59 | be a "partof". That parent **must** be defined by the user or it is a hard error 60 | - SPC and TST artifacts have auto-partof elements of the higher-order type (see 61 | [[SPC-name]]. This element is **not required** to exist, but if it does 62 | they will be linked automatically. 63 | 64 | A node can always be partof another node of the same type. In addition, the following type links are allowed 65 | 66 | ```dot 67 | 68 | ``` 69 | 70 | 71 | # SPC-read-family 72 | The method of determining family is fairly straightforward, as is 73 | detailed in the graph below: 74 | 75 | ```dot 76 | digraph G { 77 | [[.parent]] -> { "if" [label="if elem-len > 1"; shape=diamond] }; 78 | "if" -> "return None" [label = "no"]; 79 | "if" -> {"clone raw string" [ 80 | shape=box; 81 | ]} -> {"pop last element and create new Name" [ 82 | shape=box; 83 | ]} -> "return new name"; 84 | 85 | [[.auto_partof]] -> { if_req [label="type is REQ"; shape=diamond] }; 86 | if_req -> "return None" [label="yes"]; 87 | if_req -> {"get higher-order type" [ 88 | shape=box; 89 | ]} -> {"clone raw name" [ 90 | shape=box; 91 | ]} -> {"swap type with higher-order one" [ 92 | shape=box; 93 | ]} -> "return new Name"; 94 | } 95 | ``` 96 | 97 | # [[.auto]] 98 | Once family is created and the artifacts are loaded, the artifacts have 99 | to be automatically linked to their parent+auto_partof. This is easy 100 | to determine given the artifacts that exist. 101 | 102 | Note: make sure to ONLY link to artifacts that exists! 103 | 104 | # [[.deauto]] 105 | In order to reserialize the artifacts, their "auto" partof has to be unlinked 106 | -------------------------------------------------------------------------------- /design/data/implemented.md: -------------------------------------------------------------------------------- 1 | # SPC-impl 2 | partof: REQ-data 3 | ### 4 | Implementing artifacts is fairly straight forward: 5 | - [[.done]]: the artifact can define itself as done. If it does this, it must 6 | not have any subnames and must not be implemented (linked) in source. 7 | - [[.subnames]]: subnames can be defined in the `text` field of the artifact 8 | (see the beginning of this line for an example!) 9 | - [[SPC-read-impl]]: source code can link to either the artifact itself or one 10 | of its subnames through `#ART-name` or `#ART-name.sub` respectively. 11 | - 12 | 13 | 14 | # SPC-read-impl 15 | partof: SPC-impl 16 | ### 17 | ## Loading source code (implementation) links 18 | 19 | ### [[.load]]: Loading Locations 20 | The process for loading implementation locations is fairly straightforward: 21 | - Define the regular expression of valid names. Valid names inclue: 22 | - `SRC` and `TST` types ONLY. 23 | - Any valid postfix name (i.e. `SPC-foo-bar-baz_bob`) 24 | - (optional) a sub-name specified by a period (i.e. `SPC-foo.sub_impl`). 25 | - Walk the `code_paths`, iterating over each line for the regex and pulling 26 | out any `Name` or `SubName` locations. 27 | 28 | This results in two maps for each file: 29 | - `Name => CodeLoc` 30 | - `SubName => CodeLoc` 31 | 32 | ## Lints 33 | All lints related to source code are only WARNINGS 34 | 35 | - [[.lint_done]]: an artifact with its `done` field set is also linked 36 | in code. 37 | - [[.lint_exists]]: the artifact name does not exists but it does not specify the 38 | linked 39 | - [[.lint_subname_exists]]: the artifact name exists but the artifact does not specify 40 | the linked subname. 41 | 42 | ### [[.join]]: Joining Locations 43 | The `Name` and `SubName` maps from each file are joined into two large maps 44 | respectively (with any collisions put in the linting vectors which are also 45 | joined). 46 | 47 | We must then construct a map of `Name => Implementation` in order for later 48 | steps to construct the full `Artifact` object. We do this by: 49 | - Constructing a map of `Name => Map`, where `Name` is the 50 | prefix/name of the underlying `SubName`s. 51 | - Building the `Name => Implementation` map by: 52 | - Draining the `Name => CodeLoc` map and inserting `Implementation` objects. 53 | - Draining the just created `Name => Map` and either 54 | modifying or inserting `Implementation` objects. 55 | 56 | > Note: we do not worry about whether such `Name` or `SubName`s actually exist. 57 | > That is the job of a later linting step. -------------------------------------------------------------------------------- /design/data/modify.md: -------------------------------------------------------------------------------- 1 | # SPC-modify 2 | partof: REQ-data 3 | ### 4 | The modify operation takes in only the `project_path` and an array of 5 | `ArtifactOp` (see [[SPC-structs]]). 6 | 7 | From there, the control flow and high level architecture are 8 | as follows: 9 | 10 | ```dot 11 | digraph G { 12 | node [ 13 | shape=box; 14 | ]; 15 | 16 | edge [weight=10]; 17 | 18 | {start [shape=oval]} 19 | -> {read1 [label="read(project_path)" shape=cylinder]} 20 | -> {if_compare_id [ 21 | label="compare ids: orig w/ load?"]} 22 | -> {update [ 23 | label="perform updates and\n create new project"]} 24 | -> {backup [label="backup orig files" shape=cylinder]} 25 | -> {save [label="save new project to disk" shape=cylinder]} 26 | -> {read2 [label="read(project_path)" shape=cylinder]} 27 | -> {clean [label="clean (delete)\nbackup files" shape=cylinder]} 28 | -> {return [label="return new project" shape=oval]}; 29 | 30 | // error paths 31 | read1 -> {read1_err [label="ERR: db\ncorrupted by user" 32 | shape=oval fontcolor=red]} 33 | [label=err fontcolor=red]; 34 | if_compare_id -> {compare_err [label="ERR: not\nupdated" 35 | shape=oval fontcolor=red]} 36 | [label=err fontcolor=red]; 37 | update -> {update_err [ 38 | label="ERR: return lints" shape=oval fontcolor=red]} 39 | [label=err fontcolor=red]; 40 | read2 -> {restore [label="restore backups" fontcolor=red shape=cylinder]} 41 | [label=err fontcolor=red]; 42 | restore -> {read2_err [label="ERR: internal error" 43 | fontcolor=red shape=oval]}; 44 | 45 | {rank=same {read1, read1_err}}; 46 | {rank=same {if_compare_id, compare_err}}; 47 | {rank=same {update, update_err}}; 48 | {rank=same {read2, restore}}; 49 | {rank=same {clean, read2_err}}; 50 | } 51 | ``` 52 | 53 | Overall this is *relatively simple*. The only new stuff is: 54 | - [[.compare_id]]: compare the `orig_hash` of the requested changes to the hashes 55 | of the loaded values. If they don't match it means that the person requesting changes 56 | did so *with an out of date version of the artifact*. This is a no-no! 57 | - [[SPC-modify-update]]: update the loaded project with the requested changes. 58 | - [[.backup]]: backup files by moving them to (for example) `path/to/file.md` -> 59 | `path/to/file.md.art_bk`. Restoring is just moving them back to their 60 | original place. Cleaning is just deleting them. 61 | 62 | > This requires a LOT of filesystem operations, some of them seemingly 63 | > redundant. However, I believe all of them are justified. Theoretically we 64 | > could remove the "checking" one at the very end, but I prefer to keep it for 65 | > a *very* long time. 66 | 67 | 68 | # SPC-modify-update 69 | We are given a `Vec` and loaded `Project` and we want to perform 70 | the requested updates on the project, ensuring there are no new errors. 71 | 72 | The basic process is: 73 | - Ensure that there are no conflicts in the `ArtifactOp`'s original `HashIm`s 74 | or new `HashIm`s. For instance, ensure that they aren't trying to delete 75 | and create the same `HashIm`. 76 | - We _already have_ the project as a `Map`. 77 | - Note: we don't care in the next phase about whether `Name`s colide. We are 78 | hashed by `HashIm`, NOT by `Name`! 79 | - We simply perform the operations requested -- blindly changing the artifacts. 80 | - `ArtifactOp::Create` is inserting the `HashIm` into the map with the new 81 | artifact. 82 | - `ArtifactOp::Update` is removing the original `HashIm` and inserting the 83 | new one. 84 | - `ArtifactOp::Delete` is deleting the requested `HashIm` 85 | - We then rebuild the project and do all _error level_ lints. -------------------------------------------------------------------------------- /design/data/name.md: -------------------------------------------------------------------------------- 1 | # SPC-name 2 | partof: REQ-data 3 | ### 4 | The following attributes must be definable by the user: 5 | - `name`: the artifact name must be given in the form `ART-name`, where `ART` 6 | is used to determine the type (see below). 7 | - `done`: if any string is given, the artifact is "defined as done", meaning it 8 | is 100% complete for both implementation and test. 9 | - `partof`: a list (or compressed syntax) of artifact names which this artifact 10 | is a "partof". Valid and automatic links are defined in [[SPC-family]]. 11 | - `text`: the description of the artifact which can contain "soft links" to 12 | other artifacts as well as to code implementations. 13 | 14 | ## [[.type]]: Artifact Type 15 | The type of an artifact is simply its prefix, which must be one of: 16 | - `REQ`: requirement 17 | - `SPC`: design specification 18 | - `TST`: test specification 19 | 20 | The order of precedence is: 21 | - `REQ` is "higher order" than `SPC` or `TST` 22 | - `SPC` is "higher order" than `TST` 23 | 24 | ```dot 25 | digraph G { 26 | graph [rankdir=LR; splines=ortho] 27 | REQ -> SPC -> TST 28 | } 29 | ``` 30 | 31 | See [[SPC-family]] for how these are related. 32 | 33 | ## [[.attrs]]: Attributes/Getters 34 | 35 | The `Name` type shall be the exported "key" of artifacts. Internally it is 36 | reference counted, externally it exposes itself with the following methods: 37 | - `Name.ty`: get the name's type 38 | - `Name.from_str(s)`: create or automatically load the name. 39 | - `Name.as_str()`: get the string representation of the name. This must always 40 | be the same string as the user gave. 41 | - `Name.key_str()`: get the name's "key" representation 42 | 43 | Internally the name is an atomically reference counted pointer (`Arc`), meaning 44 | that cloning it is extremely cheap. -------------------------------------------------------------------------------- /design/data/structs.md: -------------------------------------------------------------------------------- 1 | # SPC-structs 2 | partof: REQ-data 3 | ### 4 | This requirement details the high level `struct`s and `enum`s that must be 5 | exported by this module, as well as their features. 6 | 7 | In many cases this would be a *specification*, but since this is a library, 8 | the exported structs and their characteristics practically ARE the 9 | requirement. 10 | 11 | It's critical that the valid types are defined at a high level, since 12 | they determine how everything works together. 13 | 14 | ### Exported Types 15 | These are the types that make up the exported "product" of this library. The 16 | major type is the **Artifact** and its associated **Name**. 17 | 18 | TODO: the original graph broke with the update to newer graphiz. Rewrite with the format below. 19 | 20 | ```dot 21 | digraph G { 22 | node [shape=record]; 23 | Animal [ 24 | label = 25 | "{Animal 26 | \l|+ name : string 27 | \l+ age : int 28 | \l|+ die() : void 29 | \l}" 30 | ] 31 | } 32 | ``` 33 | 34 | ### Raw Data Types 35 | These types define the "raw data" format of artifact and are only used 36 | for de/serializing. 37 | 38 | #### [[.artifact_raw]]: ArtifactRaw: (stored with key of `Name`) 39 | - done: `Option[String]` 40 | - partof: `Option[HashSet[Name]]` 41 | - text: `Option[TextRaw]` 42 | 43 | #### [[.text_raw]]: TextRaw: just a newtype with some serialization guarantees 44 | to make it prettier and ensure serialization is possible between 45 | all of the supported formats. 46 | 47 | ### Intermediate (`Im`) Data Types 48 | Intermediate "stripped down" forms of the artifact. These types are used for: 49 | - linting after reading the project 50 | - inteacting with the CRUD interface. 51 | 52 | #### [[.artifact_op]]: ArtifactOp: 53 | - `Create(ArtifactIm)`: create an artifact, it must not already exist. 54 | - `Update(HashIm, ArtifactIm)`: update the artifact with the specified hash. 55 | - `Delete(HashIm)`: delete the artifact with the specifed hash. 56 | 57 | This is the "operation" command used by [[SPC-modify]] for modifying artifacts. 58 | `Read` is ommitted as it is covered by [[SPC-read]]. 59 | 60 | #### [[.artifact_im]]: ArtifactIm: 61 | - name: `Name` 62 | - file: `PathAbs` 63 | - partof: `Set` (auto-partofs are stripped) 64 | - done: `Option` 65 | - text: `String` 66 | 67 | The `ArtifactIm` is used to create a unique 128 bit hash of the artifacts and 68 | for specifying *what* should be updated when an update is requested. 69 | 70 | This is also the primary type used when linting. 71 | 72 | #### HashIm: 73 | This is simply a 128 bit SipHash created by the [`siphasher` crate][1]. 74 | 75 | [1]: https://doc.servo.org/siphasher/sip128/struct.Hash128.html 76 | 77 | 78 | ## Type Details 79 | 80 | **Artifact**: ([[.artifact]]) the artifact is the primary exported type. It contains: 81 | - `name`: the unique identifier of the artifact. 82 | - `file`: the file where the artifact is defined. 83 | - `partof` and `parts`: automatic and user-defined relationship to other 84 | artifacts where `B in A.partof` means that B is a "parent" of A. 85 | More details are in [[SPC-family]]. 86 | - `completed`: the `spc` and `tst` completion ratios, detailing how much of 87 | the artifact's specification and test design has been implemented. 88 | - `text`: the user defined text in the markdown format. 89 | - `impl_`: how the artifact is implemented (if it is implemented at all). Can 90 | be `Done(str)`, `Code(ImplCode)` or `NotIMpl`. 91 | - `subnames`: a list of subnames defined in `text` using `{{.subname}}` 92 | except `[[]]` instead of `[[]]`. These can be linked in code to complete 93 | the artifact. 94 | - `orig_hash`: the original hash of the `ArtifactIm` this was created from. 95 | 96 | **Name**: 97 | - name is of the form `ART-name` where ART is one of {`REQ`, `SPC` or `TST`} 98 | - more details are in [[SPC-name]]. 99 | 100 | **Impl**: 101 | - Defines how the artifact is implemented. 102 | - `Done`: can be "defined as done" through the `done` field in the 103 | `ArtifactRaw`. 104 | - `Code`: can be implemented in code, where source code just puts `#ART-name` 105 | anywhere to mark an artifact as implemented. -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | build-frontend: 2 | cargo-web deploy -p artifact-frontend --release --target=wasm32-unknown-unknown 3 | 4 | check: build-frontend 5 | cargo check -p artifact-app -j$(( $(nproc) * 3)) 6 | 7 | build: build-frontend 8 | cargo build -p artifact-app -j$(( $(nproc) * 3)) 9 | 10 | build-release: build-frontend 11 | cargo build -p artifact-app --release -j$(( $(nproc) * 3)) 12 | 13 | test: build-frontend 14 | cargo test -p artifact-app -j$(( $(nproc) * 3)) 15 | -------------------------------------------------------------------------------- /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | __pycache__ 3 | -------------------------------------------------------------------------------- /scripts/db.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vitiral/artifact/2b46103a2f8a4012b4f0555fbcf3cc151c93a6af/scripts/db.dump -------------------------------------------------------------------------------- /scripts/interact.py: -------------------------------------------------------------------------------- 1 | """Interact with the artifact server. 2 | 3 | TODO: this is still a work in progress. We need: 4 | - an Artifact data type with from_dict and to_dict methods 5 | and an `__init__` that we can use for making artifacts 6 | - all methods should ONLY accept and return the Artifact 7 | data type 8 | - better command line interface for interacting with the API 9 | 10 | """ 11 | 12 | from __future__ import print_function 13 | 14 | import argparse 15 | import code 16 | import pprint 17 | 18 | from py_helpers.json_rpc import JsonRpc 19 | 20 | 21 | class CrudApi(JsonRpc): 22 | """Class for interacting with the artifact CRUD server API.""" 23 | 24 | def create_artifacts(self, params): 25 | """create a list of artifacts.""" 26 | payload = { 27 | 'method': 'CreateArtifacts', 28 | 'params': params, 29 | } 30 | return self.put(self.address, json=payload) 31 | 32 | def read_artifacts(self, params=None): 33 | """read the artifacts in a list.""" 34 | payload = { 35 | 'method': 'ReadArtifacts', 36 | 'params': params, 37 | } 38 | r = self.put(self.address, json=payload) 39 | r.raise_for_status() 40 | return r.json() 41 | 42 | def update_artifacts(self, params): 43 | """update the list of artifacts. 44 | 45 | Artifacts must already exist. 46 | 47 | """ 48 | payload = { 49 | 'method': 'UpdateArtifacts', 50 | 'params': params, 51 | } 52 | return self.put(self.address, json=payload) 53 | 54 | def delete_artifacts(self, params): 55 | """delete the list of artifact ids.""" 56 | payload = { 57 | 'method': 'DeleteArtifacts', 58 | 'params': params, 59 | } 60 | return self.put(self.address, json=payload) 61 | 62 | 63 | def parse_args(args=None): 64 | """parse cmdline arguments.""" 65 | parser = argparse.ArgumentParser() 66 | parser.add_argument( 67 | 'address', nargs='?', 68 | default="http://127.0.0.1:5373", help='address of artifact server') 69 | 70 | parser.add_argument( 71 | '-i', '--interactive', 72 | help='open python shell to interact with the server', 73 | action='store_true') 74 | 75 | return parser.parse_args(args=args) 76 | 77 | 78 | def readline_setup(exports): 79 | """setup readline completion, if available. 80 | 81 | :param exports: the namespace to be used for completion 82 | :return: True on success 83 | 84 | """ 85 | try: 86 | import readline 87 | except ImportError: 88 | # no completion for you. 89 | readline = None 90 | return False 91 | else: 92 | import rlcompleter 93 | readline.set_completer( 94 | rlcompleter.Completer(namespace=exports).complete) 95 | return True 96 | 97 | 98 | # pylint: disable=unused-variable 99 | def start_interactive(api): 100 | """start an interactive shell for the API. 101 | 102 | :param CrudApi api: the CrudApi session object. 103 | 104 | """ 105 | # make pretty-printing easier 106 | pp = pprint.pprint 107 | 108 | create = api.create_artifacts 109 | read = api.read_artifacts 110 | update = api.update_artifacts 111 | delete = api.delete_artifacts 112 | 113 | local = locals() 114 | exports = globals().copy() 115 | exports.update(local) 116 | 117 | # completion for global and local namespace 118 | readline_setup(exports) 119 | # dir() will only show locals() 120 | code.interact(banner=__doc__, local=local) 121 | 122 | 123 | def main(): 124 | """execute as a script.""" 125 | args = parse_args() 126 | api = CrudApi(args.address) 127 | if args.interactive: 128 | start_interactive(api) 129 | else: 130 | raise NotImplementedError('sorry, the rest is not implemented, yet') 131 | 132 | 133 | if __name__ == '__main__': 134 | main() 135 | -------------------------------------------------------------------------------- /scripts/lic_header.txt: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2017 Garrett Berg, vitiral@gmail.com 2 | * 3 | * Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be 6 | * copied, modified, or distributed except according to those terms. 7 | */ 8 | -------------------------------------------------------------------------------- /scripts/license.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | SOURCE = 'source' 4 | OLD_HEADER = 'old_header' 5 | NEW_HEADER = 'new_header' 6 | 7 | parser = argparse.ArgumentParser() 8 | parser.add_argument(SOURCE) 9 | parser.add_argument(OLD_HEADER) 10 | parser.add_argument(NEW_HEADER) 11 | 12 | args = parser.parse_args() 13 | 14 | with open(args.source) as f: 15 | source = f.read() 16 | 17 | with open(args.old_header) as f: 18 | old_header = f.read() 19 | 20 | with open(args.new_header) as f: 21 | new_header = f.read() 22 | 23 | with open(args.source, 'w') as f: 24 | f.truncate(0) 25 | f.write(source.replace(old_header, new_header)) 26 | -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | selenium 3 | pytest 4 | pylint 5 | docformatter 6 | autopep8 7 | toml 8 | aenum 9 | --------------------------------------------------------------------------------