├── .gitignore ├── AUTHORS ├── CHANGELOG.md ├── CONTRIBUTING.md ├── CREDITS.md ├── GUILD ├── LICENSE ├── Makefile ├── README.md ├── VERSION ├── conf └── gitolite.conf ├── configure ├── doc ├── consensus.md ├── faq.md ├── file-structure.md ├── issues │ ├── closed │ │ ├── basic_commit.md │ │ ├── configure_local.md │ │ ├── file_templates.md │ │ ├── init_flat.md │ │ ├── register_flat.md │ │ └── status_flat.md │ └── open │ │ ├── commit_contribution.md │ │ ├── contribute_XP_only.md │ │ └── issue_vote.md ├── ledger.md ├── roadmap.md ├── src │ ├── gitguild_mirror_network.dia │ ├── gitguild_mirror_network.jpg │ ├── guild_genesis.dia │ ├── guild_genesis.jpg │ ├── guild_network.dia │ ├── guild_network.jpg │ ├── personal_genesis.dia │ ├── personal_genesis.jpg │ ├── personal_network.dia │ ├── personal_network.jpg │ ├── second_member_joins_guild.dia │ ├── second_member_joins_guild.jpg │ ├── third_member_joins_guild.dia │ └── third_member_joins_guild.jpg ├── templates.md └── transactions.md ├── gitguild ├── h └── pre-commit-gg-only ├── keydir ├── gitguild.pub └── isysd.pub ├── ledger ├── account.ledger ├── chain.ledger ├── check.ledger ├── commodity.ledger ├── equity.ledger ├── equity.parent ├── tag.ledger └── transaction.ledger ├── t ├── helpers.sh ├── run_tests.sh ├── test_tx_engine.sh └── unsafe_install_test.sh └── template ├── add_GUILD.patch ├── add_general_project_files.patch ├── add_member_authors.patch ├── clean_gitolite_admin.patch ├── fork_repo.patch ├── isysd_contribution_1.patch ├── ledger_basics.patch ├── paid_contribution.patch ├── personal_ledger_init.patch └── register_personal_gitguild_ledger.patch /.gitignore: -------------------------------------------------------------------------------- 1 | generated_check.ledger 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | isysd ira@gitguild.com 5C3586F6 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | This project adheres to [Semantic Versioning](http://semver.org/). 5 | 6 | This Change Log format is suggested by 7 | 8 | 9 | 10 | ## 0.2.9 (2017-01-01) 11 | 12 | #### Added 13 | 14 | * Install and configure gitguild 15 | * Ledger for this guild 16 | * isysd becomes member -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Feedback and contributions are very welcome! 4 | 5 | ## A GitGuild Project 6 | 7 | This project uses [GitGuild](https://github.com/GitGuild/gitguild) software to govern itself and all contributions. Please [install](https://github.com/GitGuild/gitguild#install) the client to ensure you meet the strict configuration and usage requirements. These include, but are not limited to the following. 8 | 9 | | Rule | Description | 10 | |-------|----------------| 11 | | Must sign | Every commit must be GPG signed by a member listed in the AUTHORS file. | 12 | | Consensus branches | The `master` and `gitguild` branches are reserved for consensus. Only commits approved by XP vote can be merged. | 13 | | Member branches | A member's branch is their vote on the state and contents of the chain. | 14 | | Higher | Every commit must have a higher `:Height` than it's parent. | 15 | | Highest | Consensus is the highest valid branch of a guild. This should be mirrored to master and the guild's own branch as commits are made to member branches. | 16 | | Max Depth | Each member can only vote up to their total `:Height` on each parent hash. | 17 | 18 | The first three rules are all git best practices. These rules, and the automation of execution of checks on them, ensure a complete chain of responsibility for each change. Incomplete usage of gpg signing is not nearly good enough, as Mike Gerwitz points out in [A Git Horror Story: Repository Integrity With Signed Commits](https://mikegerwitz.com/papers/git-horror-story.html). 19 | 20 | "[H]ow can you be sure that their commits are actually their own? Furthermore, how can you be sure that any commits they approve (or sign off on using git commit -s) were actually approved by them? 21 | 22 | That is, of course, assuming that they have no ill intent. For example, what of the pissed off employee looking to get the arrogant, obnoxious co-worker fired by committing under the coworker’s name/email? What if you were the manager or project lead? Whose word would you take? How would you even know whom to suspect?" 23 | 24 | The answer to these questions is strict standards and enforcement, i.e. rules 1-3. 25 | 26 | The last three rules are all for [ledger](https://ledger-cli.org) use, and ensure consensus is calculated and enforced. Git actions are recorded by spending XP in the ledger in `Height` and `Depth` accounts. The amount of XP in the `Height` of any commit determines it's acceptance or rejection by the organization, and therefore it's mergability into master. 27 | 28 | ## Payment 29 | 30 | Contributors can request payment in GitGuild coin (XGG) as part of the contribution, and are allowed to redeem this XGG for BTC, DASH or other assets. If the commit is approved by the other members, the XGG will be counted as Income, also triggering a corresponding XP increase for the contributor. 31 | 32 | Like every change made to a guild, this payment request process is templated in a patch file, and should be run using `gitguild tx build`. In this case the tx name is `paid_contribution`. 33 | 34 | Though there are no set limits or rules on how much you can ask to be paid, remember that the pay is subject to review and approval by your peers. It is the very people reviewing your code that ultimately decide any pay you receive. 35 | 36 | ## Vulnerability reporting (security issues) 37 | 38 | If you find a significant vulnerability, or evidence of one, 39 | please send an email to the security contacts that you have such 40 | information, and we'll tell you the next steps. 41 | For now, the security contacts are: 42 | isysd , and 43 | cindy-zimmerman . 44 | 45 | Please use the PGP keys provided in the AUTHORS file to encrypt your message! 46 | 47 | ### Copyright 48 | 49 | This file adapted from the Linux Foundation's Core Infrastructure Initiative's [CONTRIBUTING.md](https://github.com/linuxfoundation/cii-best-practices-badge/blob/master/CONTRIBUTING.md). 50 | 51 | ##### Open Source License (MIT) 52 | 53 | All (new) contributed material must be released under the [MIT license](./LICENSE). 54 | All new contributed material that is not executable, including all text when not executed, is also released under the [Creative Commons Attribution 3.0 International (CC BY 3.0) license](https://creativecommons.org/licenses/by/3.0/) or later. 55 | -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | The maintainers, contributors, and members of this guild would like to thank the following for essential prior contributions. 4 | 5 | Without these foundation blocks, our chain would not be able to grow tall and thick. 6 | 7 | ### GNU 8 | 9 | So basic, even git wouldn't work without it, the GNU toolkit is used extensively by gitguild. 10 | Additionally, the GNU standards were inspirational for a number of example documents and formats. 11 | 12 | ### Linux Foundation's Core Infrastructure Initiative 13 | 14 | The greatest source of standards and example documents is definitely the CII. This includes but is not limited to the CHANGELOG, CONTRIBUTING, CREDITS, and AUTHORS file formats. 15 | 16 | ### git 17 | 18 | If there is one core foundation to the gitguild stack, it has to be git. 19 | Git is the water that guilds swim in. Thank you git for the open ocean, full of diverse ecosystems. 20 | 21 | ### GnuPG 22 | 23 | There is a saying "don't roll your own crypto." Thanks to GnuPG, we have an almost universally respected, flexible crypto backbone. 24 | Thank you GnuPG for doing the heavy lifting, and carrying the weight to git, email, and so many other areas. 25 | 26 | ### Ledger-cli 27 | 28 | How do you herd cats? Count them very carefully. Twice. Thanks to ledger-cli, the perfect plaintext accounting system was ready and waiting to drop into a git repo for version control. 29 | 30 | ### gitolite 31 | 32 | Gitolite was a late find but natural fit for gitguild development. Comprehensive permissions inside a git repo, including ssh keyring... it is just begging to be decentralized. 33 | We're honored to try extending gitolite into a P2P network. 34 | 35 | ### Individual People 36 | 37 | + Ira Miller aka isysd 38 | + Cindy Zimmerman 39 | + Andre Haynes 40 | + d3brouille 41 | + et4te 42 | + welshjf 43 | 44 | -------------------------------------------------------------------------------- /GUILD: -------------------------------------------------------------------------------- 1 | NAME gitguild 2 | LAST_TRANSACTION paid_contribution 3 | EPOCH_TIME 1483288581 4 | 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 GitGuild developers 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DESTDIR ?= /usr/bin 2 | USE_GITHUB ?= true 3 | USE_GITOLITE ?= true 4 | 5 | GG_DIR = $(HOME)/gitguild 6 | GIT_HOME = $(shell echo ~git) 7 | USER_NAME := $(shell git config user.name) 8 | USER_EMAIL := $(shell git config user.email) 9 | IDENT_REMOTE = "" 10 | 11 | gpg := $(shell which gpg) 12 | check_or_install_gpg = if [ "$(gpg)" = "" ]; then \ 13 | sudo apt-get install gnupg2; \ 14 | fi 15 | 16 | # TODO other distros and OSes 17 | check_or_install_ledger = if [ "$(shell which ledger))" = "" ]; then \ 18 | releasestr:=$(shell cat /etc/*-release); \ 19 | if [ "$(shell echo "$(releasestr)" | grep 'Ubuntu' )" != "" ]; then \ 20 | echo "install ledger from PPA?"; \ 21 | read ledgerppa; \ 22 | echo; \ 23 | if [ "$( echo "$(ledgerppa)" | grep '[yY].*' )" != "" ]; then \ 24 | sudo add-apt-repository ppa:mbudde/ledger; \ 25 | sudo apt-get update; \ 26 | sudo apt-get install ledger; \ 27 | fi \ 28 | fi \ 29 | fi 30 | 31 | ssh := $(shell which ssh ) 32 | check_or_install_ssh = if [ "$(ssh)" = "" ]; then \ 33 | sudo apt-get install ssh; \ 34 | fi 35 | 36 | # create and/or arrange ssh keys 37 | setup_ssh = if [ -e "$(HOME)/.ssh/$(USER_NAME).pub" ]; then \ 38 | echo "found ssh key to use $(HOME)/.ssh/$(USER_NAME).pub"; \ 39 | elif [ -f "$(HOME)/.ssh/id_rsa.pub" ]; then \ 40 | echo "found default id_rsa.pub ssh key to use, making a symbolic link with \ 41 | username"; \ 42 | ln -sf $(HOME)/.ssh/id_rsa $(HOME)/.ssh/$(USER_NAME); \ 43 | ln -sf $(HOME)/.ssh/id_rsa.pub $(HOME)/.ssh/$(USER_NAME).pub; \ 44 | else \ 45 | ssh-keygen -t rsa -b 4096 -C $(USER_EMAIL) -f $(HOME)/.ssh/$(USER_NAME); \ 46 | fi 47 | 48 | setup_github = if [ "$(USE_GITHUB)" = "true" ] && [ ! -d $(GG_DIR)/ok.sh ]; then \ 49 | git clone https://github.com/whiteinge/ok.sh.git $(GG_DIR)/ok.sh; \ 50 | sudo ln -sf $(GG_DIR)/ok.sh/ok.sh $(DESTDIR)/ok.sh; \ 51 | _=$( ok.sh create_repo $(USER_NAME) "$(USER_NAME)'s personal guild" ); \ 52 | fi 53 | 54 | # Optional for now, but gitolite is the server of choice for gitguild. 55 | # Gitguild will build toward a p2p architecture where all users 56 | # will run gitolite on their primary devices. 57 | # renames gitolite-admin repo to USER_NAME 58 | setup_gitolite = [ "$(USE_GITOLITE)" = "true" ]; then \ 59 | if [ ! -d /usr/lib/gitolite ]; then \ 60 | cd /tmp; \ 61 | if [ ! -d gitolite ]; then \ 62 | git clone https://github.com/isysd/gitolite.git; \ 63 | fi; \ 64 | cd gitolite; \ 65 | sudo mkdir -p /usr/lib/gitolite; \ 66 | sed -z -i.bak "s/\# GL_ADMIN_REPO => \"gitolite-admin\"/ GL_ADMIN_REPO => \"$(USER_NAME)\"/g" src/lib/Gitolite/Rc.pm; \ 67 | sudo ./install -to /usr/lib/gitolite; \ 68 | sudo ln -sf /usr/lib/gitolite/gitolite /usr/bin/gitolite; \ 69 | cp "$(HOME)/.ssh/$(USER_NAME).pub" "/tmp/$(USER_NAME).pub"; \ 70 | sudo -H -u git sh -c 'gitolite setup -pk /tmp/$(USER_NAME).pub -m "guild seeded w gitolite-admin template"'; \ 71 | sudo rm -fR $(GIT_HOME)/repositories $(GIT_HOME)/.gitolite; \ 72 | sudo -H -u git sh -c 'gitolite setup -pk /tmp/$(USER_NAME).pub -m "guild seeded w gitolite-admin template"'; \ 73 | sudo chmod -R g+rwx $(GIT_HOME)/repositories; \ 74 | sudo chmod -R g+rwx $(GIT_HOME)/.gitolite*; \ 75 | sudo ln -sf $(GIT_HOME)/repositories $(HOME)/repositories; \ 76 | sudo ln -sf $(GIT_HOME)/.gitolite $(HOME)/.gitolite; \ 77 | sudo ln -sf $(GIT_HOME)/.gitolite.rc $(HOME)/.gitolite.rc; \ 78 | fi; \ 79 | fi 80 | 81 | uninstall_gitolite = if [ "$(USE_GITOLITE)" = "true" ]; then \ 82 | sudo rm -fR $(GIT_HOME)/repositories $(HOME)/repositories $(GIT_HOME)/.gitolite $(HOME)/.gitolite $(HOME)/.gitolite.rc $(GIT_HOME)/.gitolite.rc /usr/lib/gitolite /usr/bin/gitolite; \ 83 | fi 84 | 85 | uninstall_github = if [ "$(USE_GITHUB)" = "true" ]; then \ 86 | rm -fR $(GG_DIR)/ok.sh; \ 87 | sudo rm -fR $(DESTDIR)/ok.sh; \ 88 | fi 89 | 90 | clone_ident = if [ "$(USE_GITOLITE)" = "true" ]; then \ 91 | gitguild clone $(USER_NAME) file://$(GIT_HOME)/repositories/$(USER_NAME).git; \ 92 | else \ 93 | gitguild clone $(USER_NAME); \ 94 | fi; \ 95 | cd $(GG_DIR)/$(USER_NAME); \ 96 | gitguild template build gitguild/template/clean_gitolite_admin.patch; \ 97 | gitguild template build gitguild/template/add_member_authors.patch; \ 98 | gitguild template build gitguild/template/add_general_project_files.patch; \ 99 | gitguild template build gitguild/template/ledger_basics.patch; \ 100 | gitguild template build gitguild/template/personal_ledger_init.patch; \ 101 | gitguild template build gitguild/template/add_GUILD.patch; \ 102 | export LAST_TRANSACTION=init_personal; \ 103 | gitguild tx finish; \ 104 | cat ledger/equity.*; \ 105 | git add .gitignore; \ 106 | git add -A; \ 107 | git commit -q -m "initialize identity guild"; \ 108 | gitguild push 109 | 110 | clone_gitguild = if [ ! -d "$(GG_DIR)/gitguild" ]; then \ 111 | ./gitguild clone "gitguild" git@mirror.gitguild.com:gitguild; \ 112 | fi 113 | 114 | fork_gitguild = if [ ! -d "$(GIT_HOME)/repositories/gitguild.git" ]; then \ 115 | gitguild fork "gitguild" git@mirror.gitguild.com:gitguild; \ 116 | fi 117 | 118 | rm_user_dir = if [ "$(USER_NAME)" != "" ]; then \ 119 | rm -fR $(GG_DIR)/$(USER_NAME); \ 120 | fi 121 | 122 | install: 123 | $(call check_or_install_gpg) 124 | $(call check_or_install_ledger) 125 | $(call check_or_install_ssh) 126 | $(call setup_ssh) 127 | $(call setup_gitolite) 128 | $(call setup_github) 129 | $(call clone_gitguild) 130 | sudo ln -sf $(GG_DIR)/gitguild/gitguild $(DESTDIR)/gitguild 131 | 132 | personal: 133 | $(call clone_ident) 134 | $(call fork_gitguild) 135 | 136 | test: 137 | cd "./t"; \ 138 | ./run_tests.sh all 139 | 140 | testinstall: 141 | cd "./t"; \ 142 | ./run_tests.sh install 143 | 144 | uninstall: 145 | $(call rm_user_dir) 146 | sudo rm -f $(DESTDIR)/gitguild 147 | $(call uninstall_gitolite) 148 | $(call uninstall_github) 149 | 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gitguild 2 | 3 | __WARNING This is still experimental software! Use at your own risk.__ 4 | 5 | Governance for a git repository, using PGP identities. 6 | 7 | + Issue digital value tokens 8 | + Create, sign, and enforce contracts 9 | + Participate in projects in a democratic, decentralized manner 10 | 11 | ## Try it out 12 | 13 | Just download and run `gitguild`. 14 | 15 | Since this version is a bourne shell script, it should be runnable as a standalone program on most linux and MacOS systems. More work is necessary to make the script Windows compatible, but there are no barriers. 16 | 17 | As a command line supplement to git, the help menus are comprehensive. 18 | 19 | ``` 20 | gitguild A helpful blockchain in a script. 21 | 22 | Usage: 23 | gitguild user Manage your gitguild user. 24 | gitguild tx build and check transactions. 25 | gitguild ledger Perform gitguild-related ledger actions. 26 | gitguild clone () Clone a guild from optional remote. 27 | gitguild push git push with extra checks and remotes. 28 | gitguild fork Fork a guild with one or more remotes. 29 | gitguild setup-repo Setup remotes and hooks in current git repo. 30 | gitguild template Create and list tx templates. 31 | gitguild help Show the general help. 32 | gitguild version Show the program version. 33 | 34 | Options: 35 | gitguild -h Show command help details. 36 | ``` 37 | 38 | ## Install 39 | 40 | Installing in the specific location shown below is a more permanent and full featured method, providing transaction templates and a subscription to changes in the core. 41 | 42 | ``` 43 | mkdir $HOME/gitguild 44 | git clone git://mirror.gitguild.com:gitguild $HOME/gitguild/gitguild 45 | cd $HOME/gitguild/gitguild 46 | ./configure # will ask for password for new 'git' user 47 | make install 48 | ``` 49 | 50 | __*System restart will be required at this point!*__ 51 | 52 | The install process created a new 'git' user and group on your system, and additionally changed the hostname. These require a system reboot before taking affect, and the next step will not work without it. 53 | 54 | After your reboot, you can create your personal guild, if you haven't done so on a previous occasion. 55 | 56 | ``` 57 | make personal 58 | ``` 59 | 60 | For more details on the output of this full install process, read `./doc/file-structure.md`. 61 | 62 | ##### Pre-requisites 63 | 64 | The following programs are required to be installed on the system prior to running gitguild. Note that git and ledger-cli must have recent versions! Depending on your system, the configure and make commands may help you install these. (Ubuntu only, for now) 65 | 66 | + [git](https://git-scm.com/downloads) 2.0+ 67 | + [Ledger-cli](http://ledger-cli.org/download.html) 3.0+ (2.x is not good enough!) 68 | + [GnuPG](https://gnupg.org/download/index.html) 69 | 70 | ### Configure your user 71 | 72 | This should happen during the `./configure` step of the above setup phase, or the first time gitguild is run. Gitguild has high expectations for the local git configuration, and may ask for some settings to be filled in. 73 | 74 | ``` 75 | WARNING: Git user.name not configured. 76 | 77 | Please enter your git name followed by [ENTER] 78 | ``` 79 | 80 | You may also see some guessing or generation helpers. Just walk through it until it stops bothering you for more configuration. 81 | 82 | ``` 83 | guessing 84 | Detected one or more keys matching your name or email. 85 | The one you want is probably among these. 86 | 4E4FBA61 5C3586F6 87 | 88 | Please enter your git signingkey followed by [ENTER] 89 | ``` 90 | 91 | Assuming you satisfy the script's prerequisites, it will no longer ask you these questions. It may, however, warn you that you are not in the AUTHORS file. This is expected until you register for a specific guild. 92 | 93 | ##### Github Integration 94 | 95 | Thanks to [ok.sh](https://github.com/whiteinge/ok.sh), gitguild can also integrate with [github](https://github.com) seamlessly. Just run `make install` with `USE_GITHUB=true` (the default), and it will add your github credentials to `~/.netrc` as described in [ok.sh setup](https://github.com/whiteinge/ok.sh#setup). 96 | 97 | Note that gitguild asks for the following permissions for your token: 98 | 99 | + [x] repo (three boxes) 100 | + [ ] admin:repo_hook 101 | + [ ] admin:org_hook 102 | + [ ] user:email 103 | + [ ] read:public_key 104 | + [ ] read:gpg_key 105 | 106 | The unchecked ones are not currently used, but planned for the future. Unlisted ones will probably never be needed by this program. 107 | 108 | If you wish to disable github integration, run `configure` and `make install` with argument `USE_GITHUB=false`. 109 | 110 | ## Additional Resources 111 | 112 | Guilds keep all documentation, issues, and other project-relevant information inside the repository. There are a number of detailed documents in the top level of this docs directory that are a good place to start. 113 | 114 | ### General 115 | 116 | + docs/faq.md 117 | 118 | ### Technical 119 | 120 | + docs/roadmap.md 121 | + docs/file-structure.md 122 | + docs/templates.md 123 | + docs/ledger.md 124 | 125 | ## Help 126 | 127 | Make an issue on github, or in the `docs/issues` directory, if you are a member. 128 | 129 | Join us on IRC chat channel `#gitguild` on freenode (see https://freenode.net/kb/answer/chat). 130 | 131 | ## License 132 | 133 | To quote the Linux Foundation's [Core Infrastructure Initiative](https://github.com/linuxfoundation/cii-best-practices-badge), from whom we borrowed so much: 134 | 135 | All material is released under the [MIT license](./LICENSE). 136 | All material that is not executable, including all text when not executed, 137 | is also released under the 138 | [Creative Commons Attribution 3.0 International (CC BY 3.0) license](https://creativecommons.org/licenses/by/3.0/) or later. 139 | In SPDX terms, everything here is licensed under MIT; 140 | if it's not executable, including the text when extracted from code, it's 141 | "(MIT OR CC-BY-3.0+)". 142 | 143 | See CREDITS file for more on CII and other excellent projects that helped gitguild become reality. -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.2.9 2 | -------------------------------------------------------------------------------- /conf/gitolite.conf: -------------------------------------------------------------------------------- 1 | @admins = isysd 2 | 3 | repo @all 4 | RW refs/.* = @admins 5 | R = @all 6 | 7 | repo gitguild 8 | RW isysd = isysd 9 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # parse command line args for make analogs 3 | USE_GITHUB=true 4 | for p in "$@"; do 5 | USE_GH=$(echo "$p" | grep 'USE_GITHUB' | grep -o '\w*$') 6 | if [ "$USE_GH" != "" ]; then 7 | USE_GITHUB=$USE_GH 8 | fi 9 | done 10 | 11 | # This sets up your local git configuration. 12 | # It is a pre-requisite for installation. 13 | ./gitguild user status 14 | echo 15 | USER_NAME=$(git config user.name) 16 | 17 | # This runs the ok.sh configuration, if USE_GITHUB is true 18 | if [ "$USE_GITHUB" = "true" ]; then 19 | if [ ! -f "$HOME"/.netrc ] || \ 20 | [ "$(grep api.github.com "$HOME"/.netrc)" = "" ]; then 21 | echo "Enter your github api token. Will not display." 22 | echo "Create a token at https://github.com/settings/tokens if you need to." 23 | stty -echo 24 | read token 25 | stty echo 26 | if [ "$token" = "" ]; then 27 | echo "If you do not want github, rerun with USE_GITHUB=false" 28 | exit 2 29 | fi 30 | { 31 | echo "machine api.github.com" 32 | echo " login ""$USER_NAME" 33 | echo " password ""$token" 34 | echo 35 | } >> "$HOME"/.netrc 36 | echo "github configured." 37 | echo 38 | fi 39 | fi 40 | 41 | # As explained in the echo, it is necessary to set the hostname. 42 | hostname=$(hostname) 43 | if [ "$hostname" != "$USER_NAME" ]; then 44 | echo Need to set the system "hostname" to your git user name. 45 | echo The reasoning is that a limited git and ssh server are created. 46 | echo Once the system has a public name, it should be a logical name, 47 | echo and should not leak personal information unintentionally. 48 | echo 49 | if [ -f "/etc/sysconfig/network" ]; then 50 | sudo sed -i "s/HOSTNAME=$hostname/HOSTNAME=$USER_NAME/" /etc/sysconfig/network 51 | sudo hostname "$USER_NAME" 52 | elif [ -f "/etc/hostname" ]; then 53 | sudo sed -i "s/$hostname/$USER_NAME/" /etc/hostname 54 | sudo sed -i "s/ $hostname/ $USER_NAME/" /etc/hosts 55 | sudo hostname "$USER_NAME" 56 | fi 57 | fi 58 | 59 | gitu=$(id -u git) 60 | if [ "$?" != 0 ] || [ "$gitu" = "" ]; then 61 | echo To further protect the system, a "git" system user and group will be created. 62 | echo These will isolate the server processes and files from the rest of your system. 63 | echo 64 | echo "Please choose a password for this new \"git\" user." 65 | stty -echo 66 | read gitpass 67 | stty echo 68 | if [ "$gitpass" = "" ]; then 69 | echo "It is highly recommended to set a strong password for the git user!" 70 | echo "The security of this user is the security of the rest of your system." 71 | exit 2 72 | fi 73 | sudo groupadd git 74 | sudo useradd -m -g git git 75 | if [ "$?" != 0 ]; then 76 | echo "Could not create git user. Bailing." 77 | exit 1 78 | fi 79 | echo "git:$gitpass" | sudo chpasswd 80 | echo "git user created!" 81 | echo 82 | # also add your current user to git group 83 | sudo usermod -a -G git "$USER" 84 | newgrp git 85 | echo "Also added your current user to the 'git' group" 86 | echo "You will have full access to the git group files, but" 87 | echo "The git user will not have access to your files." 88 | echo 89 | # ensure group has ownership of all of git's files 90 | sudo chown -R git:git /home/git/ 91 | fi 92 | 93 | -------------------------------------------------------------------------------- /doc/consensus.md: -------------------------------------------------------------------------------- 1 | # Consensus 2 | 3 | ## Abstract 4 | 5 | Git is a flexible version control system in use by tens of millions of collaborators worldwide. Git [stores data](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects) in sha1 hash trees, and [supports](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work) gpg signing of commits (since v1.7.9). With strict usage guidelines, these cryptographic utilities create a blockchain made up of gpg-signed, sha1-hashed commits. 6 | 7 | ## Proof of Labor 8 | 9 | A chain of signed commits is hearafter referred to as Proof of Labor. Proof of Labor is a flexible, meritocratic mining system. 10 | 11 | Each block of data is made up of a pgp-signed git commit. This commit consistitutes some Labor performed by one or more members of the guild. The other members of the guild then vote on accepting the PR or not by merging the commit or creating a fork. 12 | 13 | Once a commit has been merged into the master branch, it may not be reverted or overwritten without being detected by other members of the guild. Git guild are immutable unless a fork aka rebase is explicitely voted for. This is similar to other blockchains, where immutability is subject to maintaining consensus. 14 | 15 | #### Crypto 16 | 17 | While this system has not yet been reviewed by cryptographers, it should not be controversial. Proof of Labor uses standard, well established tools in a downright orthodox way. 18 | 19 | GNU Privacy Guard aka GPG is a popular encryption program first released in 1999. GPG is open source software package compliant with [RFC 4880](https://tools.ietf.org/html/rfc4880), which is the IETF standards track specification of OpenPGP. The latest version (2.0.30) supports RSA, ElGamal and DSA signing, as well as a number of ciphers, hashes, and compression algorithms. It is commonly used for encrypting and/or signing emails, and is growing in use in the git community. 20 | 21 | Git was developed as a file system, by Linus Torvalds, in 2005. The SHA1 hash tree that git uses was introduced in that first version. Since git has become one of the most popular software projects of all time, this hash tree has seen a lot of real world use, as well as development. Key to the hash tree is that all files are hashed into a commit, along with the parent commit(s). Git's hash tree is a directed acyclic graph. This means it is a one directional, immutable tree with branches and branch resolution. Loops, rewriting history, and a number of other logical inconsistencies are prevented. 22 | 23 | Since git v1.7.9, released in 2012, git has supported GPG signing commits. This release was the final technical pre-requisite for Proof of Labor. 24 | 25 | ## Summary 26 | 27 | If this seems too easy, you're not alone. For software developers, git feels like water to a fish. It is challenging to discover something new about the environment you survive in. 28 | 29 | The contributors to Proof of Labor are amazed at how broad the applications seem to be. The natural contracting language and strong reputation system of PoL are unique in a blockchain. Due to this broad scope, we have erred on the side of abstraction over specification. While Proof of Labor could be even more loose, and many alternate implementations are possible, we believe this is a flexible, minimal working ruleset. 30 | 31 | Proof of Labor is complimentary with PoW systems in many ways, and could even be applied after the fact as a governance layer to blockchains like Bitcoin. It could be used as an oracle by other blockchains, or lend them sidechain functionality. It is not likely to be as fast or as directly scalable, but perhaps with advanced sidechain usage, even massive parallel processing could be possible. Most likely, however, an optimal hybrid will emerge after much experimentation. 32 | -------------------------------------------------------------------------------- /doc/faq.md: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions (FAQ) 2 | 3 | ### The GitGuild Organization 4 | 5 | ##### Mission Statement 6 | 7 | The GitGuild is a development cooperative building tools, methodologies, and operational models that empower FLOSS projects to achieve financial and technical independence without compromising on principles. 8 | 9 | ##### What is the GitGuild? 10 | 11 | The GitGuild is a community of developers, designers and other contributors, dedicated to open, transparent, and mutually-profitable organizational principles. This is managed through universally accessible and naturally democratic tools of [Git](http://git-scm.com/), [PGP](https://gnupg.org/), and [ledger-cli](http://ledger-cli.org/). 12 | 13 | ##### How does a Guild operate? 14 | 15 | "The" GitGuild is different from "a" Guild using the GitGuild methodologies. 16 | 17 | A Guild operates by establishing a constitution (aka CONTRIBUTING.md), contracts (templates), and recruiting members. Documents are stored publicly, accessible by all, and members sign every action with pgp. 18 | 19 | Each guild must maintain a ledger allocating XP to users, which they then spend voting on commits. The gitguild software uses this XP commit voting structure to calculate the consensus for the organization. 20 | 21 | ##### How does the GitGuild operate? 22 | 23 | "The" GitGuild is different from "a" Guild using the GitGuild methodologies. 24 | 25 | The GitGuild is an experimental Guild that was established to empower open source software development teams. We function like any other guild, but using experimental tools and models before they're recommended for general use. 26 | 27 | In addition to developing the core technology, the GitGuild maintains a registry of active guilds, and may provide some hosting/mirroring services. This is essential for cross referencing guilds, and keeping them in sync. Over time, other organization guilds will bridge these gaps between individuals, but at the start, the GitGuild will be the only option available. 28 | 29 | ##### Does the GitGuild share everything it produces? 30 | 31 | Yes. Our software is all released under a MIT license. Legal, operational, and other methodological documents are released under a Creative Commons license. 32 | 33 | ### What projects does the GitGuild maintain? 34 | 35 | ##### Core 36 | 37 | + [gitguild command software](https://github.com/gitguild/gitguild) 38 | + [gitguild.com website](https://github.com/gitguild/gitguild_website) (10% complete) 39 | 40 | ##### Other Projects 41 | 42 | + [bitjws](https://github.com/deginner/bitjws) - Bitcoin message signing and JWS combined to an autentication standard similar to bitid. 43 | + De application framework - This really has no name, but we have a whole application framework built up around bitjws, swagger, and sqlalchemy. Multiple github repositories for servers, clients, etc. 44 | + [desw](https://github.com/deginner/desw) - a multi-currency hot wallet service available via API. 45 | + [De Broker](https://github.com/deginner/de-broker) - a fixed-price cryptocurrency brokerage ala Shapeshift 46 | + [De Exchange Node](https://github.com/deginner/exchange-node) - a bid/ask exchange engine and orderbook. 47 | + De Cosigner - An automated cosigning service to compliment bitcore or other multisignature wallet clients. 48 | + [Trade Manager](https://github.com/deginner/trade-manager) - An exchange client manager for manual or automated trading on popular cryptocurrency exchanges. 49 | 50 | ### GitGuild and Me 51 | 52 | ##### Can I personally become a GitGuild member? 53 | 54 | Yes! Anyone can join, and use our software, XGG coin, as well as network services. The GitGuild exists to develop software, however, and if you wish to earn XP in the GitGuild, you must do some constructive work and earn XGG Income. 55 | 56 | GitGuild members are also subject to XP vote approval, and must maintain a minimum of 50% approval to access organization services. 57 | 58 | ##### Does the GitGuild have any partners? Support external teams? 59 | 60 | Yes, we support and are supported by the following projects and more. 61 | 62 | + [Tigo CTM](http://tigoctm.com) 63 | + [Dash](https://dash.org) 64 | + [200 Social](http://200social.com) 65 | + [Bitt](https://bitt.com) 66 | + [Coinapult](https://coinapult.com) 67 | + [Crypto Capital](https://cryptocapital.co) 68 | + [VeMine](https://vemine.org) 69 | 70 | ##### Can the GitGuild help my team build XYZ? Monetize our open source project? Reach internet users? 71 | 72 | Yes! As an internet-based community of builders, we have all of the expertise and many of the components ready to assemble. 73 | 74 | Our specialties are: 75 | 76 | + Digital currency issuance, management, liquidity, and launch 77 | + Trustless applications and services 78 | + Market services, such as exchange, brokerage, trading 79 | 80 | ##### Does the GitGuild provide financing for startup projects? 81 | 82 | Yes, and no. If your project is a technical fit, and has commercial potential, then the GitGuild may offer to finance your project with GitGuild coin (XGG). This can be spent on development of your project with qualified, peer-reviewed GitGuild contributors. For many projects, this is sufficient to reach MVP, and market validation or failure. 83 | 84 | Of course, the value paid to the contributors who build your MVP has to come from somewhere. Any XGG issued has to be in return for equal or greater value to the GitGuild. For instance, you may be asked to give up equity, pay digital tokens, or to make a revenue sharing agreement with the GitGuild. 85 | 86 | All such agreements require XP approval of 66%. 87 | 88 | 89 | ### GitGuild vs. Other Blockchains 90 | 91 | ##### Is GitGuild more or less private than Bitcoin? 92 | 93 | That is a tough question to answer. GitGuild has very strong identities, and no throwaway addresses. These mean that parties to a transaction know a lot about each other, at minimum email and gpg key. 94 | 95 | On the other hand, the nature of the Bitcoin blockchain is inherently public. All addresses and transactions *must* be published in Bitcoin. This is not so for GitGuild, where private networks of ssh tunnels allow for completely private blockchains. 96 | 97 | These private gitguild chains would have 100% encrypted traffic, using ssh keys, and could encrypt any messages to each other with their known email and gpg keys. Such an organization would be very private indeed. 98 | 99 | ##### Is GitGuild more or less decentralized than Bitcoin? 100 | 101 | Definitely less, for now. GitGuild's P2P network is still under construction, and so [github](https://github.com) is most likely to be a central reference point for most guilds. Even after the P2P network launch, it can be expected that many projects will prefer their current git host over a change requiring some work. 102 | 103 | ##### Is GitGuild more or less scalable than Bitcoin? 104 | 105 | Interesting question. The answer is not clear. 106 | 107 | A single guild could probably not scale nearly as well as Bitcoin, because the data structures are significantly less efficient. The consensus algorithm is also not nearly as robust, designed to mirror human workflow, not provable computer work. 108 | 109 | On the other hand, GitGuild is designed for parallelisation. Could a million guilds operate in parallel? Would that be more efficient than Bitcoin could be? How efficient can Bitcoin become with lightning, rootstock, and other parallelisation models? We don't know the answers to these questions yet. 110 | -------------------------------------------------------------------------------- /doc/file-structure.md: -------------------------------------------------------------------------------- 1 | # System File Structure 2 | 3 | | Directory | File | Description | 4 | |-----------|------|-------------| 5 | | `~/gitguild` | * | The default guild installation directory. Where repos are cloned for local work. | 6 | | `~/gitguild/` | * | Your personal guild's local clone. | 7 | | `~/gitguild/gitguild` | * | Your clone of the gitguild source w/ templates & ledger. | 8 | | `~git/repositories` | * | The gitolite server repository data dir. DO NOT TOUCH! | 9 | 10 | By default, all guilds are installed in `~/gitguild`, and your personal one will be in `~/gitguild/`. It is likely that there will also be a local clone of this repo at `~/gitguild/gitguild`. 11 | 12 | ### `git` system user and group 13 | 14 | On a system level, gitolite is installed under a new user `git`, in a new group `git`. This is a security measure, since gitolite runs a limited ssh and git server under that user. 15 | 16 | The specific way this protects user privacy is that the system username is required in ssh requests. I.e. `ssh username@gitserver.com` If no new user is created then username will be your main system user, exposing that name to the world. If, bits forbid, someone managed to get around the limiting ssh permissions, they would be on a sandboxed user without sudo privileges or special file access. 17 | 18 | ### hostname 19 | 20 | The hostname of your system must be the same as your git username. This is because in the p2p gitguild network, your system has become a public git server. Your hostname is exposed to the public, and so it should not read "Andy's bathroom tablet" or something equally compromising. Setting it to the git username allows for easy identification when your friends want to get the latest from you. 21 | 22 | In short, this: 23 | 24 | ``` 25 | $ ssh git@1.1.1.1 info 26 | hello Jennifer, this is git@andy... 27 | ``` 28 | 29 | Sure beats: 30 | 31 | ``` 32 | $ ssh andyweinbaum@1.1.1.1 info 33 | hello Jennifer, this is andyweinbaum@Andy's bathroom tablet... 34 | ``` 35 | 36 | Setting a hostname and creating a system user sound like a lot for a simple shell script, but they're both necessary for security and privacy. 37 | 38 | ### Your Personal Guild 39 | 40 | Upon installation, a personal guild is created for you at `~/gitguild/`. This is your personal blockchain, accounting, and file storage area. You can chose to share it with select people securely using ssh and gpg authentication. 41 | 42 | This sharing will be important as your identity guild is also a permanent record of reference for your perspective on various balances, transactions and contracts. 43 | 44 | ##### Gitolite Configuration 45 | 46 | Each guild is intended to be hosted on a [gitolite](http://gitolite.com/) server. In fact, one should have been installed locally during setup. Gitolite was chosen largely due to it's simple and in-repository configuration system, including permissions and authorisation. 47 | 48 | For the most part these files should be automatically managed and you should not change them. 49 | 50 | | Path from Repo | File | Description | 51 | |-----------|------|-------------| 52 | | `/conf/` | gitolite.conf | The guild's gitolite configuration file. Sets permissions for all users and repositories. | 53 | | `/keydir/` | *.pub | The guild's member's public ssh keys. For gitolite authentication. | 54 | 55 | ##### (Mostly) Standard Documents 56 | 57 | The goal of this first release of gitguild is to reach open source developers. Conversion of existing projects is a high priority, and so we've stayed as close to "standards" of open source development as possible. The [GNU standards](https://www.gnu.org/prep/standards/standards.html) were inspirational but not strictly followed. 58 | 59 | | Path from Repo | File | Description | 60 | |-----------|------|-------------| 61 | | `/` | AUTHORS | The guild's member registry. All members must register here. | 62 | | `/` | VERSION | The guild's version. Differ from gitguild software version. | 63 | | `/` | CHANGELOG.md | A log of material changes. | 64 | | `/` | CONTRIBUTING.md | Entry document to legal terms of participation and contribution. Any/all others should link from here. | 65 | 66 | ##### Unique Guild Documents 67 | 68 | | Path from Repo | File | Description | 69 | |-----------|------|-------------| 70 | | `/` | GUILD | The guild's description file. Highest level summary data. | 71 | | `/ledger/` | * | The guild's accounting and voting records. (ledger-cli data) | 72 | | `/template/` | * | The guild's transaction templates. (patch files) | 73 | -------------------------------------------------------------------------------- /doc/issues/closed/basic_commit.md: -------------------------------------------------------------------------------- 1 | # Commit Guild without ledger 2 | 3 | ### commands 4 | 5 | | Command | Arguments | Description | 6 | |---------|-----------|-------------| 7 | | commit | all, message | Prepare CHANGELOG.md, commit message, etc., and then run git commit, signing with GPG | 8 | 9 | ### tests 10 | 11 | | Name | Assertions | Description | 12 | |------|------------|-------------| 13 | | commit_empty | warning, suggest git add | Attempt to commit in an unchanged branch. | 14 | | commit | Commit signed and created with all files prepared. | Attempt to commit in a changed branch. | 15 | | commit_bad_status | warning, give status message | Attempt to commit in a branch returning a bad status. | 16 | -------------------------------------------------------------------------------- /doc/issues/closed/configure_local.md: -------------------------------------------------------------------------------- 1 | # Configure local GitGuild settings 2 | 3 | ### commands 4 | 5 | | Command | Arguments | Description | 6 | |---------|-----------|-------------| 7 | | config | username, email, signingkey | Get the username, email and signingkey from git, or set them if empty. | 8 | 9 | ### tests 10 | 11 | | Name | Assertions | Description | 12 | |------|------------|-------------| 13 | | config_fresh | prompted, keys set | When configuring for the first time, user should be prompted to fill in any missing git config settings. After that, values are returned. | 14 | -------------------------------------------------------------------------------- /doc/issues/closed/file_templates.md: -------------------------------------------------------------------------------- 1 | # Make and check file templates 2 | 3 | ### commands 4 | 5 | | Command | Arguments | Description | 6 | |---------|-----------|-------------| 7 | | make_template | input_file | Create a template file out of a source file. For patching and validation of commits. | 8 | 9 | ### tests 10 | 11 | | Name | Assertions | Description | 12 | |------|------------|-------------| 13 | | status_local_changes | local changes represent a valid commit, and are scored | Check the local changes against the guild's permitted templates. | 14 | 15 | 16 | ### Comments 17 | 18 | ##### isysd 19 | 20 | The best way to manage these templates seems to be through diffs and patches. That is, each template represents a permittable diff profile. Each commit must match one of these profiles for the other members to recognize it as valid. 21 | 22 | Another problem is metadata. The metadata will have to include at minimum the number of votes required to confirm a transaction. So far experimentation has been with json schemas for this metadata, but a custom unified template file structure is more efficient. Json is badly suited for a unified file structure as it doesn't preserve whitespace, newlines and other important data. 23 | -------------------------------------------------------------------------------- /doc/issues/closed/init_flat.md: -------------------------------------------------------------------------------- 1 | # Initialize Guild using CII standards. 2 | 3 | ### commands 4 | 5 | | Command | Arguments | Description | 6 | |---------|-----------|-------------| 7 | | init | license, register | Create the required guild file structure, inspired by general git standards enumerated by CII. (CONTRIBUTING.md, LICENSE, AUTHORS, CHANGELOG.md, doc, etc.) | 8 | 9 | ### tests 10 | 11 | | Name | Assertions | Description | 12 | |------|------------|-------------| 13 | | init_empty | (LICENSE, AUTHORS, CHANGELOG.md, CONTRIBUTING.md, doc) exists | Guild files created from empty directory. | 14 | | init_full | warning, no action | Attempt to initialize over an existing guild. | 15 | -------------------------------------------------------------------------------- /doc/issues/closed/register_flat.md: -------------------------------------------------------------------------------- 1 | # Register for a Guild using CII standards. 2 | 3 | ### commands 4 | 5 | | Command | Arguments | Description | 6 | |---------|-----------|-------------| 7 | | register | username, fingerprint, email | Add a user to the AUTHORS file. | 8 | 9 | ### tests 10 | 11 | | Name | Assertions | Description | 12 | |------|------------|-------------| 13 | | register | user added to AUTHORS | success | 14 | | register_duplicate_username | warning, no action | error | 15 | | register_duplicate_email | warning, no action | error | 16 | | register_duplicate_fingerprint | warning, no action | error | 17 | -------------------------------------------------------------------------------- /doc/issues/closed/status_flat.md: -------------------------------------------------------------------------------- 1 | # Get status of Guild using CII standards. 2 | 3 | ### commands 4 | 5 | | Command | Arguments | Description | 6 | |---------|-----------|-------------| 7 | | status | username, email | Check the status of the current guild, relative to the user given (default to current user) | 8 | 9 | ### tests 10 | 11 | | Name | Assertions | Description | 12 | |------|------------|-------------| 13 | | status_empty | warn, suggest init | Attempt to get status of non-guild directory. | 14 | | status | guild status and user status returned | Attempt to get status of good guild directory. | 15 | | status_username | guild status and (another) user status returned | Attempt to get status of good guild directory using another username. | 16 | -------------------------------------------------------------------------------- /doc/issues/open/commit_contribution.md: -------------------------------------------------------------------------------- 1 | # Contribute to a ledger using only XP 2 | 3 | ### commands 4 | 5 | | Command | Arguments | Description | 6 | |---------|-----------|-------------| 7 | | commit | all, message, submit | Also merge contributions and any other local changes to the 'voting' branch. | 8 | 9 | ### tests 10 | 11 | | Name | Assertions | Description | 12 | |------|------------|-------------| 13 | | commit_good | commit to user branch made, merge commit from user to voting branch made | Create a valid contribution then commit it. | 14 | | commit_bad_contribution | warn, no action | If contribution is not correctly formed, do not allow commit. | 15 | -------------------------------------------------------------------------------- /doc/issues/open/contribute_XP_only.md: -------------------------------------------------------------------------------- 1 | # Contribute to a ledger using only XP 2 | 3 | ### commands 4 | 5 | | Command | Arguments | Description | 6 | |---------|-----------|-------------| 7 | | contribute | XP | Add contribution transaction to the ledger with the given number of XP going to the current user. | 8 | 9 | ### tests 10 | 11 | | Name | Assertions | Description | 12 | |------|------------|-------------| 13 | | init_ledger | (ledger, ledger/definitions.ledger, ledger/coa.ledger, ledger/changelog.ledger, ledger/checks.ledger) | initialize with ledger files | 14 | | contribute | ledger file updated, status pass | success | 15 | | contribute_bad | status fail, commit fail | Ensure that status and commit fail appropriately when an invalid contribution is in the ledger. | 16 | -------------------------------------------------------------------------------- /doc/issues/open/issue_vote.md: -------------------------------------------------------------------------------- 1 | # Vote on an issue using XP 2 | 3 | ### commands 4 | 5 | | Command | Arguments | Description | 6 | |---------|-----------|-------------| 7 | | vote | issue_id, y/n | Add vote transaction on the given issue. | 8 | 9 | ### tests 10 | 11 | | Name | Assertions | Description | 12 | |------|------------|-------------| 13 | | vote_y | yes vote entered against real issue | Create a valid issue then vote on it. | 14 | | vote_n | no vote entered against real issue | Create a valid issue then vote on it. | 15 | | vote_no_issue | warn, no action | vote entered against invalid issue | 16 | 17 | -------------------------------------------------------------------------------- /doc/ledger.md: -------------------------------------------------------------------------------- 1 | # Ledger 2 | 3 | Each guild should keep a ledger file using the [ledger-cli](http://ledger-cli.org) data format. This double entry accounting system is both human readable and mathematically accurate. Furthermore it is flexible enough to track or even create any currency, commodity, or digital token. 4 | 5 | ### Account Structure 6 | 7 | Account structure is quite complex in the GitGuild, creating a symmetry between this ledger and the git tree itself. 8 | 9 | A number of complex and potentially long account names may be difficult to read, but they're quite organized. The basic structure is as follows. 10 | 11 | `user_name:accounting_category:repository:branch:parent_commit_hash:metadata` 12 | 13 | ##### Voting and Consensus 14 | 15 | If the account is a child of `Height` or `Depth`, then the last level is reserved for XP votes. Members spend XP from the guild's `Depth` account and assign it to member's `Height` for specific commits. This is done automatically when merging a commit, mathematically signalling the approval and weight of the merger's reputation. 16 | 17 | ##### Account Level 1 18 | 19 | *user_name* 20 | 21 | The top level of a guild ledger is the users themselves. Each account (except the guild account) belongs to exactly one user. Since no user can have the same name as the guild, this is a conflict free namespace with clear borders and responsibility. 22 | 23 | For instance, the GitGuild communal accounts are `gitguild:*`, and in the gitguild ledger members have individual accounts, like isysd's `isysd:*`. 24 | 25 | ##### Account Level 2 26 | 27 | *accounting_category* 28 | 29 | The second level accounts are mostly traditional: `Income`, `Expenses`, `Assets`, `Liabilities`, `Equity`. These should be familiar to anyone with an accounting background, but ledger-cli also has an [excellent introduction](http://ledger-cli.org/3.0/doc/ledger3.html#Structuring-your-Accounts). 30 | 31 | The second level also has two additional options related to voting: `Height`, `Depth`. Depth is where XP originates, and where each member spent XP is counted. Height is where XP are spent and issues votes are counted. So each XP originates in some `Depth` and then goes to a `Height`. These are key to determining consensus, and enforcing the guild's rules. 32 | 33 | Each transaction requiring an XP vote must list itself in the signing user's Height. The more + XP that any account accumulates, the more standing it has in the guild. The guild's total height is how forward progress is measured, and no commit can have a lower total height than it's parent. 34 | 35 | ##### Account Level 3 36 | 37 | *repository* 38 | 39 | From the third level on, accounts mirror the git structure closely. This is a sort of address system, allowing a ledger consumer to identify the repository, branch, and commit associated with a balance. Level 3 is the repository level. Assuming the client already has a remote list for each repository, it is enough information to begin the search. 40 | 41 | It is important to note that each user must have a personal guild, which is a repository. Every guild must be a repository, but not every repository is a guild. Still, with every possible name combination, this repository namespace has no room for non-user-name, non-guild-name repositories. Such repositories cannot safely be recorded in a guild ledger. 42 | 43 | ##### Account Level 4 44 | 45 | *branch* 46 | 47 | Inside each repository are branches. These are also named after users, and represent each user's perspective on the repository. Again, the namespace is restricted only to the names of users and guilds, forbidding alternatives. 48 | 49 | ##### Account Level 5 50 | 51 | *parent* 52 | 53 | Parent is the SHA1 hash of the parent commit to the one containing the transaction. This is the last bit of information in the git tree address: repository, branch, commit hash. Once these are specified, the transaction is unambiguously identified and can be treated individually for voting and other accounting operations. 54 | 55 | ##### Account Level 6 56 | 57 | *metadata* 58 | 59 | Metadata might be bitcoin or dash addresses, and/or transaction hashes. Really, this area is pretty open to any string important enough to be hashed into the ledger itself. 60 | -------------------------------------------------------------------------------- /doc/roadmap.md: -------------------------------------------------------------------------------- 1 | # Alpha 2 | v0 3 | 4 | For use by GitGuild members and partners. Not intended for general user adoption. 5 | 6 | ## Experimental 7 | v0.2 8 | 9 | The GitGuild is a dynamic experiment in blockchain technology. 10 | It is immutable, but far more flexible than other blockchains. 11 | These early v0.0.x verions are experiments, meant to change over time. 12 | 13 | ### Data structures 14 | v0.2.1 15 | 16 | Experiments in data structures. These are the core contracts that make up a guild. 17 | 18 | #### Flat CII file standards 19 | v0.2.1.1 20 | 21 | Apply the CII standards to a flat repository, i.e. no submodules. This is the closest file structure we can adopt relative to existing, high quality FLOSS projects. 22 | 23 | ##### issues 24 | 25 | + [x] configure_local 26 | + [x] init_flat 27 | + [x] register_flat 28 | + [x] status_flat 29 | 30 | #### Flat basic commit 31 | v0.2.1.2 32 | 33 | Commit gpg signed, status checked, changlog entered commit. 34 | 35 | ##### issues 36 | 37 | + [x] file_templates 38 | + [x] basic_commit 39 | 40 | #### Flat XP-only ledger 41 | v0.2.2 42 | 43 | Add ledger files back in, defining an XP asset for Experience Points. Create a contribute transaction template and command to credit contributors in XP. 44 | 45 | ##### issues 46 | 47 | + [ ] contribute_XP_only 48 | 49 | #### Local git server 50 | v0.2.5 51 | 52 | Each user is to run their own git server, using gitolite. 53 | The gitolite admin repo will be merged with the guild identity repo, keeping the ledger and permissions in the same area. 54 | 55 | + [x] gitolite server setup and configuration 56 | + [x] gitolite admin repo merged with identity repo 57 | + [ ] Mirror to github 58 | 59 | #### Flat XP-only ledger with voting 60 | v0.2.6 61 | 62 | Vote on contribution (and other?) changes, over multiple GPG-signed commits. Commits should be voted on in individual branches, and after passing, merged into the guild named branch. 63 | 64 | ##### issues 65 | 66 | + [ ] issue_vote 67 | 68 | #### Pedantic and Secure Ledger 69 | v0.2.7 70 | 71 | Assure voting and other rules are enforced strictly at the ledger level. 72 | Use check.ledger to run vote count and other guild-level assertions. 73 | 74 | + [ ] commit_contribution 75 | + [ ] check own commit 76 | + [ ] check other's commit 77 | 78 | #### Document and UX test 79 | v0.2.9 80 | 81 | Clean up the code, documenting along the way. Prepare for others to review and contribute. Also use in the context of a git project, and test for helpfulness. 82 | 83 | + [ ] Account structure and relationship to voting 84 | + [ ] Height, Depth, and vote consensus 85 | + [ ] Network architecture, message flow 86 | + [x] Local software architecture, i.e. requirements, key rings, gitolite resources, git working dirs 87 | 88 | #### Alpha Test release 89 | v0.3 90 | 91 | This release will have all basic functionality, but may have bugs, even known bugs. It is intended for the GitGuild dev and QA team to familiarize themselves and give feedback before proceeding. 92 | 93 | + [ ] Package up and release to team 94 | -------------------------------------------------------------------------------- /doc/src/gitguild_mirror_network.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/gitguild_mirror_network.dia -------------------------------------------------------------------------------- /doc/src/gitguild_mirror_network.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/gitguild_mirror_network.jpg -------------------------------------------------------------------------------- /doc/src/guild_genesis.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/guild_genesis.dia -------------------------------------------------------------------------------- /doc/src/guild_genesis.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/guild_genesis.jpg -------------------------------------------------------------------------------- /doc/src/guild_network.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/guild_network.dia -------------------------------------------------------------------------------- /doc/src/guild_network.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/guild_network.jpg -------------------------------------------------------------------------------- /doc/src/personal_genesis.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/personal_genesis.dia -------------------------------------------------------------------------------- /doc/src/personal_genesis.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/personal_genesis.jpg -------------------------------------------------------------------------------- /doc/src/personal_network.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/personal_network.dia -------------------------------------------------------------------------------- /doc/src/personal_network.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/personal_network.jpg -------------------------------------------------------------------------------- /doc/src/second_member_joins_guild.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/second_member_joins_guild.dia -------------------------------------------------------------------------------- /doc/src/second_member_joins_guild.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/second_member_joins_guild.jpg -------------------------------------------------------------------------------- /doc/src/third_member_joins_guild.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/third_member_joins_guild.dia -------------------------------------------------------------------------------- /doc/src/third_member_joins_guild.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GitGuild/gitguild/a6000f2cbf8b9a31b12852a4f8003a7d00a70cb0/doc/src/third_member_joins_guild.jpg -------------------------------------------------------------------------------- /doc/templates.md: -------------------------------------------------------------------------------- 1 | # Transaction Templates 2 | 3 | Usually shortened as "templates," all gitguild transacions must correspond to one or more patch files describing the changes being made. These patterns have been pre-approved by the guild governing the transaction, with set XP voting rules for acceptance. 4 | 5 | ### Diff & Patch 6 | 7 | The core engine of gitguild's template system is GNU's [diffutils](https://www.gnu.org/software/diffutils/). Users of git are no doubt already familiar with `diff`, and maybe even `patch`. Gitguild uses these to create (diff), apply (patch), and check (reverse patch) templates. 8 | 9 | Lets look at a simple example: adding a new member to the `AUTHORS` file. This template is in `template/add_member_authors.patch`. 10 | 11 | ``` 12 | diff -cr -N -x .git -x '*.patch' /old//AUTHORS /new//AUTHORS 13 | *** /old//AUTHORS 1969-12-31 19:00:00.000000000 -0500 14 | --- /new//AUTHORS 2016-12-23 11:00:15.859360525 -0500 15 | *************** 16 | *** 0 **** 17 | --- 1 ---- 18 | + <<< user_name >>> <<< user_email >>> <<< user_signingkey >>> 19 | ``` 20 | 21 | The patch shows one line being added to the AUTHORS file. It could be run in reverse to show one line being deleted from the AUTHORS file. 22 | 23 | ### Parameters 24 | 25 | To transform a strict patch into a more flexible template, add parameters. Gitguild template parameters are surrounded by triple angle brackets. i.e. `<<< param_name >>>`. As far as the developers can tell, this is a previously unused format, which will avoid collisions with any documents under revision control. 26 | 27 | At runtime, these parameters will be replaced by the appropriate values from the context of the transaction. For instance, `<<< user_name >>>` would be the current user's name when creating a transaction using a patch, but would be the committer's name when checking said transaction. 28 | 29 | ``` 30 | $ head -n 1 AUTHORS 31 | isysd ira@gitguild.com 5C3586F6 32 | ``` 33 | 34 | ### Creating Templates 35 | 36 | To create a template, start with a git repo representing your starting state. Commit this starting state so that there are no uncommitted new or modified files. 37 | 38 | Now modify make any file changes you wish to be templated. In generating the example above, the AUTHORS file was manually edited, and the parameterized line was added. 39 | 40 | ``` 41 | $ echo "<<< user_name >>> <<< user_email >>> <<< user_signingkey >>>" >> AUTHORS 42 | ``` 43 | 44 | If you run `git status`, it should now show one or more changes against your starting commit. These can be added or untracked, it doesn't matter. The next step is to run `gitguild template create`. 45 | 46 | ``` 47 | $ gitguild template create 48 | diff -cr -N -x .git -x '*.patch' /old//AUTHORS /new//AUTHORS 49 | *** /old//AUTHORS 1969-12-31 19:00:00.000000000 -0500 50 | --- /new//AUTHORS 2016-12-23 11:00:15.859360525 -0500 51 | *************** 52 | *** 0 **** 53 | --- 1 ---- 54 | + <<< user_name >>> <<< user_email >>> <<< user_signingkey >>> 55 | ``` 56 | 57 | The patch was printed to stdout for you to review. If it looks good, route the output into a file, like so. 58 | 59 | ``` 60 | $ gitguild template create > ~/gitguild/gitguild/template/add_member_authors.patch 61 | ``` 62 | 63 | Assuming the edits were made in parameterized fashion, and no new parameters were introduced, your template is now ready to run. Congratulations! 64 | -------------------------------------------------------------------------------- /doc/transactions.md: -------------------------------------------------------------------------------- 1 | # Transactions 2 | 3 | ### Ledger Tags 4 | 5 | ### Templates -------------------------------------------------------------------------------- /gitguild: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #MIT License 3 | # 4 | #Copyright (c) 2016 GitGuild developers 5 | # 6 | #Permission is hereby granted, free of charge, to any person obtaining a copy 7 | #of this software and associated documentation files (the "Software"), to deal 8 | #in the Software without restriction, including without limitation the rights 9 | #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | #copies of the Software, and to permit persons to whom the Software is 11 | #furnished to do so, subject to the following conditions: 12 | # 13 | #The above copyright notice and this permission notice shall be included in all 14 | #copies or substantial portions of the Software. 15 | # 16 | #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | #SOFTWARE. 23 | 24 | ORIG_IFS=$IFS 25 | 26 | # Save $0 so we can shift 27 | # $1 must be a cmd. 28 | export PROG_NAME=$( echo "$0" | grep -o "[^/]*$" ) 29 | export COMMAND=$1 30 | 31 | # Git user configuration is a pre-requisite of this script. 32 | export USER_NAME=$( git config user.name ) 33 | export USER_EMAIL=$( git config user.email ) 34 | export USER_SIGNINGKEY=$( git config user.signingkey ) 35 | USER_IS_CONFIGURED=true 36 | 37 | # gitolite user home, where repos are hosted 38 | # shellcheck disable=SC2116 39 | export GIT_HOME=$(echo ~git) 40 | 41 | # default working directory, where repos are cloned 42 | export GG_DIR=$HOME"/gitguild" 43 | 44 | # Normally this should be run inside such a git repo 45 | GIT_DIR=$( readlink -f "$( git rev-parse -q --git-dir )" | grep -o ".*[^.git]" ) 46 | 47 | # change to the root of any git dir for the duration of the script 48 | if [ -d "$GIT_DIR" ]; then 49 | cd "$GIT_DIR" 50 | fi 51 | 52 | if [ "$( which ok.sh )" != "" ]; then 53 | export USE_GITHUB=true 54 | else 55 | export USE_GITHUB=false 56 | fi 57 | 58 | if [ "$( which gitolite )" != "" ]; then 59 | export USE_GITOLITE=true 60 | else 61 | export USE_GITOLITE=false 62 | fi 63 | 64 | #------------------------CLI Helpers-------------------------- 65 | 66 | USAGE_PREAMBLE=" 67 | \t$PROG_NAME\tA helpful blockchain in a script. 68 | 69 | \tUsage: 70 | " 71 | GENERAL_USAGE="\t\t$PROG_NAME help\t\tShow the general help. 72 | \t\t$PROG_NAME version\tShow the program version. 73 | 74 | \tOptions: 75 | " 76 | 77 | USAGE_SUFFIX="\t\t$PROG_NAME -h\tShow command help details." 78 | 79 | command_usage_line() { 80 | printf "\t\t%s %s\t%s" "$PROG_NAME" "$COMMAND" "$*" 81 | } 82 | subcommand_usage_line() { 83 | SUBCMD=$1 84 | shift 85 | printf "\t\t%s %s\t%s\t%s" "$PROG_NAME" "$COMMAND" "$SUBCMD" "$*" 86 | } 87 | # $1 the arg string 88 | # $2 the help 89 | command_option_line() { 90 | OPTSTR=$1 91 | shift 92 | printf "\t\t%s\t\t%s" "$OPTSTR" "$*" 93 | } 94 | 95 | 96 | #------------------------CLI Handlers----------------------------- 97 | 98 | # The main handler. Takes raw user input from command line. 99 | # $1 is the command 100 | __main() { 101 | case $1 in 102 | user) 103 | shift 104 | handle_user_cmd "$@" 105 | ;; 106 | ledger) 107 | shift 108 | get_or_set_all_cfg_values 109 | if [ ! $USER_IS_CONFIGURED ]; then 110 | exit 1 111 | fi 112 | handle_ledger_cmd "$@" 113 | ;; 114 | tx) 115 | shift 116 | get_or_set_all_cfg_values 117 | if [ ! $USER_IS_CONFIGURED ]; then 118 | exit 1 119 | fi 120 | handle_tx_cmd "$@" 121 | ;; 122 | template) 123 | shift 124 | handle_tpl_cmd "$@" 125 | ;; 126 | push) 127 | shift 128 | get_or_set_all_cfg_values 129 | if [ ! $USER_IS_CONFIGURED ]; then 130 | exit 1 131 | fi 132 | gg_push "$@" 133 | ;; 134 | clone) 135 | shift 136 | get_or_set_all_cfg_values 137 | if [ ! $USER_IS_CONFIGURED ]; then 138 | exit 1 139 | fi 140 | clone_guild "$@" 141 | ;; 142 | fork) 143 | shift 144 | get_or_set_all_cfg_values 145 | if [ ! $USER_IS_CONFIGURED ]; then 146 | exit 1 147 | fi 148 | gg_fork "$@" 149 | ;; 150 | version|--version) 151 | cat VERSION 152 | ;; 153 | setup-repo) 154 | gname=$(guess_template_param guild_name) 155 | if [ "$gname" != "" ]; then 156 | setup_repo "$gname" 157 | fi 158 | ;; 159 | *) 160 | COMMAND="user" 161 | cmdl="$( command_usage_line Manage guild users.)\n" 162 | COMMAND="tx" 163 | cmdl="$cmdl$( command_usage_line build and check transactions.)\n" 164 | COMMAND="ledger" 165 | cmdl="$cmdl$( command_usage_line Perform guild-related ledger actions. )\n" 166 | COMMAND="clone" 167 | cmdl="$cmdl$( subcommand_usage_line \ \(\\) Clone a guild from optional remote. )\n" 168 | COMMAND="push" 169 | cmdl="$cmdl$( command_usage_line git push with extra checks and remotes. )\n" 170 | COMMAND="fork" 171 | cmdl="$cmdl$( subcommand_usage_line \ Fork a guild with one or more remotes. )\n" 172 | COMMAND="setup-repo" 173 | cmdl="$cmdl$( subcommand_usage_line Setup remotes and hooks in current git repo. )\n" 174 | COMMAND="template" 175 | cmdl="$cmdl$( command_usage_line Create and list tx templates. )\n" 176 | echo "$USAGE_PREAMBLE$cmdl$GENERAL_USAGE$USAGE_SUFFIX" 177 | exit 178 | ;; 179 | esac 180 | } 181 | 182 | handle_user_cmd() { 183 | case $1 in 184 | keygen) 185 | gpgkeygen 186 | setup_ssh 187 | exit 188 | ;; 189 | unset) 190 | git config --global --unset-all user.name 191 | git config --global --unset-all user.email 192 | git config --global --unset-all user.signingkey 193 | exit 194 | ;; 195 | status) 196 | get_or_set_all_cfg_values 197 | USERSTR="$USER_NAME $USER_EMAIL $USER_SIGNINGKEY" 198 | echo "Operating as user: $USERSTR" 199 | ensure_members_uniq 200 | exit 201 | ;; 202 | *) 203 | cmdl="$( subcommand_usage_line keygen Generate and/or configure gpg \ 204 | and ssh keys)\n" 205 | cmdl="$cmdl$( subcommand_usage_line unset Unset git user configs.)\n" 206 | cmdl="$cmdl$( subcommand_usage_line status Print user status.)\n" 207 | echo "$USAGE_PREAMBLE$cmdl$GENERAL_USAGE$USAGE_SUFFIX" 208 | exit 209 | ;; 210 | esac 211 | } 212 | 213 | # $1 is now sub-command (build, check) 214 | handle_tx_cmd() { 215 | case $1 in 216 | check) 217 | shift 218 | check_tx "$@" 219 | ;; 220 | build) 221 | shift 222 | # $1 is now a tag name 223 | build_tx "$@" 224 | ;; 225 | list) 226 | list_tx_tags 227 | ;; 228 | archive) 229 | shift 230 | archive_tx_ledger "$@" 231 | ;; 232 | finish) 233 | finish_tx 234 | ;; 235 | reset) 236 | # $2 is an optional flag to pass to git clean 237 | flag="-i" 238 | if [ "$2" != "" ]; then 239 | flag=$2 240 | fi 241 | git clean "$flag" -d 242 | git reset -q --hard HEAD^ 243 | git pull -q "$USER_NAME" "$USER_NAME" 244 | ;; 245 | *) 246 | cmdl="$( subcommand_usage_line check Check the tx at HEAD or the given \ 247 | commit hash. )\n" 248 | cmdl="$cmdl$( subcommand_usage_line archive Archive any current transactions \ 249 | \(put in equity.ledger\). )\n" 250 | cmdl="$cmdl$( subcommand_usage_line build \ Build the given tx \ 251 | tag, which probably is multiple patches. )\n" 252 | cmdl="$cmdl$( subcommand_usage_line finish Perform TX finishing actions, i.e. equity.ledger. )\n" 253 | cmdl="$cmdl$( subcommand_usage_line list List the available tx tags. )\n" 254 | cmdl="$cmdl$( subcommand_usage_line reset Clean and reset to HEAD. )\n" 255 | echo "$USAGE_PREAMBLE$cmdl$GENERAL_USAGE$USAGE_SUFFIX" 256 | exit 257 | ;; 258 | esac 259 | } 260 | 261 | # $1 is now sub-command 262 | # $@ are params for the sub-command 263 | handle_tpl_cmd() { 264 | case $1 in 265 | create) 266 | shift 267 | create_patch "$@" 268 | ;; 269 | build) 270 | shift 271 | tname="$1" 272 | shift 273 | if [ "$1" != "" ] && [ "$(echo "$1" | grep .patch$ )" = "" ]; then 274 | phash="$1" 275 | shift 276 | build_tpl "$tname" "$phash" "$@" 277 | else 278 | build_tpl "$tname" "HEAD" "$@" 279 | fi 280 | ;; 281 | list) 282 | if [ "$2" = "" ]; then 283 | ls "$GG_DIR"/*/template/*.patch 284 | else 285 | shift 286 | list_tx_tag_templates "$@" 287 | fi 288 | ;; 289 | *) 290 | cmdl="$( subcommand_usage_line create Create a stub template for future \ 291 | transactions. )\n" 292 | cmdl="$cmdl$( subcommand_usage_line build \ Build the given \ 293 | template. )\n" 294 | cmdl="$cmdl$( subcommand_usage_line list List the available templates. )\n" 295 | echo "$USAGE_PREAMBLE$cmdl$GENERAL_USAGE$USAGE_SUFFIX" 296 | exit 297 | ;; 298 | esac 299 | } 300 | 301 | # $1 is the name of the guild to clone 302 | # $2 is optional remote to clone from. Assumed to be github if not specified. 303 | clone_guild() { 304 | exists=$( [ ! -d "$GG_DIR/$1" ] || echo true ) 305 | if [ "$(echo "$1" | grep -E '^[-]{1,2}h[elp]{0,3}$')" = "" ] && [ "$exists" != "true" ]; then 306 | if [ "$2" = "" ]; then 307 | url="https://github.com/$1/$1.git" 308 | else 309 | url="$2" 310 | fi 311 | git clone "$url" "$GG_DIR/$1" 312 | setup_repo "$1" 313 | else 314 | if [ "$exists" = "true" ]; then 315 | echo "$GG_DIR/$1 exists. Will not overwrite it." 316 | fi 317 | cmdl="$( subcommand_usage_line clone \ \(\\) Clone a guild from optional remote. )\n" 318 | echo "$USAGE_PREAMBLE$cmdl$GENERAL_USAGE$USAGE_SUFFIX" 319 | exit 320 | fi 321 | } 322 | 323 | # push 324 | gg_push() { 325 | branch=$( git branch | grep "\*" | tr -d "* " ) 326 | if [ "$branch" = "$USER_NAME" ]; then 327 | for remote in $( git remote ); do 328 | if [ "$( use_gitolite_push "$remote" )" ]; then 329 | gitolite push -q "$remote" "$branch" 330 | else 331 | git push -q "$remote" "$branch" 332 | fi 333 | done 334 | git checkout -q master 335 | git merge -q "$USER_NAME" 336 | # only push master to your own gitolite and github 337 | remotes=$( git remote | grep "$USER_NAME" | uniq) 338 | for remote in $remotes; do 339 | if [ "$( use_gitolite_push "$remote" )" ]; then 340 | gitolite push -q "$remote" master 341 | else 342 | git push -q "$remote" master 343 | fi 344 | done 345 | git checkout -q "$USER_NAME" 346 | else 347 | echo "You are not on your own branch. Are you sure you want to push?" 348 | read writeob 349 | echo 350 | if [ "$( echo "$writeob" | grep '[yY].*' )" != "" ]; then 351 | if [ "$( use_gitolite_push "$USER_NAME" )" ]; then 352 | gitolite push -q "$USER_NAME" "$branch" 353 | else 354 | git push -q "$USER_NAME" "$branch" 355 | fi 356 | fi 357 | fi 358 | } 359 | 360 | fork_help() { 361 | cmdl="$( subcommand_usage_line fork \ Fork a guild. )\n" 362 | echo "$USAGE_PREAMBLE$cmdl$GENERAL_USAGE$USAGE_SUFFIX" 363 | } 364 | 365 | # $1 the name of the guild to fork 366 | # $2 remote If none is provided, github is guessed. 367 | gg_fork() { 368 | if [ "$1" = "" ]; then 369 | fork_help 370 | exit 1 371 | fi 372 | remote=$2 373 | if [ "$remote" = "" ]; then # guess github 374 | remote=https://github.com/"$1/$1".git 375 | if "$(github_repo_exists "$1" "$1")" = "false"; then 376 | echo "Cannot fork $1. Try forking something else." 377 | echo 378 | fork_help 379 | exit 1 380 | fi 381 | fi 382 | # try to fork using ok.sh's github fork 383 | if [ "$USE_GITHUB" = "true" ]; then 384 | if [ "$( echo "$remote" | grep github.com )" != "" ]; then 385 | _=$( ok.sh fork_repo "$1" "$1" ) # ignore, since always returns repo data 386 | else 387 | _=$( ok.sh create_repo "$1" 2>&1 ) 388 | fi 389 | fi 390 | if [ "$USE_GITOLITE" = "true" ]; then 391 | # clone locally if necessary 392 | if [ "$( gitolite list-phy-repos | grep "$1" )" = "" ]; then 393 | git clone -q --bare "$remote" "$GIT_HOME/repositories/$1.git" 394 | gitolite setup 395 | fi 396 | # add to gitolite.conf 397 | # shellcheck disable=SC2016 398 | if [ "$( grep 'repo "$1"' "$GG_DIR"/"$USER_NAME"/conf/gitolite.conf )" = "" ]; then 399 | cd "$GG_DIR/$USER_NAME" 400 | git checkout -q "$USER_NAME" 401 | build_tx fork_repo "other_guild=$1" 402 | git add -A 403 | git commit -m "forked $1" 404 | gitguild push 405 | fi 406 | fi 407 | if [ ! -d "$GG_DIR/$1" ]; then 408 | git clone "$remote" "$GG_DIR/$1" 409 | fi 410 | # setup remotes 411 | setup_repo "$1" 412 | # register? 413 | } 414 | 415 | ledger_help() { 416 | cmdl="$( subcommand_usage_line equity Print the equity gitguild style)\n" 417 | cmdl="$cmdl$( subcommand_usage_line build Build the ledger for the current commit.)\n" 418 | echo "$USAGE_PREAMBLE$cmdl$GENERAL_USAGE$USAGE_SUFFIX" 419 | } 420 | 421 | # $1 subcommand 422 | handle_ledger_cmd() { 423 | case $1 in 424 | equity) 425 | ledger_equity 426 | ;; 427 | build) 428 | ledger_build 429 | ;; 430 | *) 431 | ledger_help 432 | exit 433 | ;; 434 | esac 435 | } 436 | 437 | #--------------Checks, setup, and installation helpers--------------- 438 | 439 | # $1 is the github user to search 440 | github_list_user_repos() { 441 | ok.sh list_repos gitguild | grep clone_url | tr -d "\"," | grep -o '[^ ]*$' 442 | } 443 | 444 | # $1 is the github user 445 | # $2 is the repo name 446 | github_repo_exists() { 447 | rf=$( ok.sh list_repos gitguild | grep github.com/"$1"/"$2" ) 448 | if [ "$rf" = "" ]; then 449 | echo "false" 450 | else 451 | echo "true" 452 | fi 453 | } 454 | 455 | # $1 is the name of the guild 456 | setup_repo() { 457 | cd "$GG_DIR/$1" 458 | # sense official github remote 459 | ghr=$(git remote -v | grep "github.com/$1/$1" | grep -o "^\w*" | uniq) 460 | if [ "$ghr" != "" ] && [ "$ghr" != "github" ]; then 461 | grep -rl "$ghr" "$GG_DIR/$1/.git" | xargs sed -i "s,$ghr,github,g" 462 | elif [ "$ghr" = "" ] && [ "$USE_GITHUB" = "true" ] && [ "$(github_repo_exists "$1" "$1")" = "true" ]; then 463 | git remote add github https://github.com/"$1"/"$1".git 464 | fi 465 | # sense personal github remote 466 | if [ "$1" != "$USER_NAME" ]; then 467 | pghr=$(git remote -v | grep "github.com/$USER_NAME/$1" | grep -o "^\w*" | uniq) 468 | if [ "$USE_GITHUB" = "true" ]; then 469 | if [ "$pghr" != "" ] && [ "$pghr" != "$USER_NAME"_gh ]; then 470 | grep -rl "$pghr" "$GG_DIR/$1/.git" | xargs sed -i "s,$pghr,$USER_NAME_gh,g" 471 | elif [ "$ghr" = "" ] && [ "$USE_GITHUB" = "true" ] && [ "$(github_repo_exists "$USER_NAME" "$1")" = "true" ]; then 472 | git remote add "$USER_NAME"_gh https://github.com/"$USER_NAME"/"$1".git 473 | fi 474 | fi 475 | fi 476 | # sense local gitolite remote 477 | if [ "$USE_GITOLITE" = "true" ]; then 478 | lgor=$(git remote -v | grep "file://.*$1" | grep -o "^\w*" | uniq) 479 | if [ "$lgor" != "" ] && [ "$lgor" != "$USER_NAME" ]; then 480 | grep -rl "$lgor" "$GG_DIR/$1/.git" | xargs sed -i "s,$lgor,$USER_NAME,g" 481 | elif [ "$lgor" = "" ] && [ "$( gitolite list-phy-repos | grep "$1" )" = "" ]; then 482 | git remote add "$USER_NAME" "file://$GIT_HOME/repositories/$1.git" 483 | fi 484 | fi 485 | # sense other gitolite remotes 486 | ogor=$(git remote -v | grep fetch | grep "git@.*:$1" | grep -o "^\w*" ) 487 | for lname in $ogor; do 488 | url=$(git remote get-url "$lname" | grep -o "^[^:]*") 489 | # shellcheck disable=SC2029 490 | ginfo=$( ssh "$url" info "$1" ) 491 | gname=$( echo "$ginfo" | grep -o '@[^ ]*' | tr -d "@" ) 492 | if [ "$lname" != "$gname" ] && [ "$( echo "$ginfo" | grep -v 'this is' | grep "$1" )" != "" ]; then 493 | grep -rl "$lname" "$GG_DIR/$1/.git" | xargs sed -i "s,$lname,$gname,g" 494 | fi 495 | done 496 | if [ "$( git branch | grep "$USER_NAME" )" = "" ]; then 497 | git checkout -b "$USER_NAME" 498 | fi 499 | # add hooks 500 | if [ -d ./h ]; then 501 | for hook in ./h/*; do 502 | if [ "$(echo "$hook" | grep pre-commit)" = "" ]; then 503 | cp "h/$hook" .git/hooks/pre-commit 504 | fi 505 | done 506 | fi 507 | } 508 | 509 | #-------------------user prep and command section-------------------------- 510 | 511 | gpgkeygen() { 512 | echo "The gpg --gen-key walk-through is about to be run." 513 | echo "For GitGuild to function, a dual key (RSA and RSA or DSA and Elgamal)" 514 | echo "is required. Other parameters (name, email) should match your" 515 | echo "git identity." 516 | echo 517 | echo "It is highly recommended to create a passphrase for your security!" 518 | echo "Your passphrase is what stops someone using your machine" 519 | echo "from stealing your identity." 520 | echo "Use a strong password, back it up and create a revocation key." 521 | echo 522 | echo "The developers recommend using a free and open source password manager." 523 | echo "The pass program is used internally, and if you like the command line," 524 | echo "it could be for you even outside of gitguild." 525 | echo "" 526 | echo "OK, ready to generate keys?" 527 | read readyono 528 | echo 529 | if [ "$( echo "$readyono" | grep '[yY].*' )" != "" ]; then 530 | gpg --gen-key 531 | else 532 | user_cfg_error "signingkey" "gpg key id" 533 | fi 534 | } 535 | 536 | # $1 is the official git config format 537 | # $2 is the user understandable format 538 | user_cfg_error() { 539 | echo "OK, to try setting your git $1 at any time, run:" 1>&2 540 | echo 1>&2 541 | echo "gitguild user status" 1>&2 542 | USER_IS_CONFIGURED=false 543 | } 544 | 545 | # $1 is the username to search for 546 | guess_cfg_from_authors_by_value() { 547 | if [ -f ./AUTHORS ]; then 548 | cfginfo=$( grep "$1" ./AUTHORS ) 549 | if [ "$cfginfo" != "" ]; then 550 | USER_NAME="$( echo "$cfginfo" | grep -o '^[^ ]*')" 551 | git config --global --add user.email "$USER_EMAIL" 552 | USER_EMAIL="$( echo "$cfginfo" | grep -o ' [^ ]* ' | tr -d ' ' )" 553 | git config --global --add user.email "$USER_EMAIL" 554 | USER_SIGNINGKEY="$( echo "$cfginfo" | grep -o '[^ ]*$' )" 555 | git config --global --add user.signingkey "$USER_SIGNINGKEY" 556 | fi 557 | fi 558 | } 559 | 560 | print_sig_guesses() { 561 | if [ "$USER_EMAIL" != "" ]; then 562 | keylist=$( gpg --list-secret-keys --fast-list-mode "$USER_EMAIL" | grep sec | \ 563 | grep -o "[A-Z0-9]\{8\} " ) 564 | elif [ "$USER_NAME" != "" ]; then 565 | keylist=$( gpg --list-secret-keys --fast-list-mode "$USER_NAME" | grep sec | \ 566 | grep -o "[A-Z0-9]\{8\} " ) 567 | fi 568 | if [ "$keylist" != "" ]; then 569 | echo "Detected one or more keys matching your name or email." 570 | echo "The one you want is probably among these." 571 | echo "$keylist" 572 | echo 573 | elif [ "$USER_EMAIL" != "" ] && [ "$USER_NAME" != "" ]; then 574 | echo "Could not detect a key matching your name or email." 575 | echo 576 | gpgkeygen 577 | fi 578 | } 579 | 580 | # $1 the git config name of the field 581 | get_cfg_by_name() { 582 | case $1 in 583 | name) 584 | echo "$USER_NAME" 585 | ;; 586 | email) 587 | echo "$USER_EMAIL" 588 | ;; 589 | signingkey) 590 | echo "$USER_SIGNINGKEY" 591 | ;; 592 | esac 593 | } 594 | 595 | # $1 the git config name of the field 596 | # $2 the value to set 597 | set_cfg_by_name() { 598 | case $1 in 599 | name) 600 | USER_NAME=$2 601 | ;; 602 | email) 603 | USER_EMAIL=$2 604 | ;; 605 | signingkey) 606 | USER_SIGNINGKEY=$2 607 | ;; 608 | esac 609 | } 610 | 611 | # $1 is the official git config format of the field name 612 | # $2 is the user understandable format 613 | get_or_set_cfg_value() { 614 | if [ "$( get_cfg_by_name "$1" )" = "" ]; then 615 | echo "WARNING: Git user.$1 not configured." 616 | echo 617 | if [ "$1" != "name" ] && [ "$( get_cfg_by_name "$1" )" = "" ]; then 618 | # try to guess based on name 619 | echo "guessing" 620 | guess_cfg_from_authors_by_value "$USER_NAME" 621 | fi 622 | if [ "$( get_cfg_by_name "$1" )" = "" ] && [ "$1" = "signingkey" ]; then 623 | print_sig_guesses 624 | elif [ "$1" = "signingkey" ]; then 625 | return 626 | fi 627 | if [ "$( get_cfg_by_name "$1" )" = "" ]; then 628 | echo "Please enter your git $1 followed by [ENTER]" 629 | read userval 630 | if [ "$userval" != "" ]; then 631 | git config --global --add user."$1" "$userval" 632 | echo 633 | set_cfg_by_name "$1" "$userval" 634 | else 635 | user_cfg_error "$2" "$3" 636 | fi 637 | fi 638 | fi 639 | } 640 | 641 | get_or_set_all_cfg_values() { 642 | get_or_set_cfg_value "name" "user name" 643 | get_or_set_cfg_value "email" "email" 644 | get_or_set_cfg_value "signingkey" "gpg key id" 645 | git config --global commit.gpgsign true 646 | } 647 | 648 | # This is a user-related check function that can be run at any point. 649 | # Exits with error status and message if members are not unique. 650 | ensure_members_uniq() { 651 | if [ -f ./AUTHORS ]; then 652 | USR_STR=$( grep "$USER_NAME $USER_EMAIL $USER_SIGNINGKEY" ./AUTHORS ) 653 | if [ "$USR_STR" != "$USER_NAME $USER_EMAIL $USER_SIGNINGKEY" ]; then 654 | echo "ERROR: current user not found in AUTHORS" 1>&2 655 | exit 1 656 | fi 657 | total=$( grep -c "^[^\n].*" AUTHORS ) 658 | names=$( grep -o '^[^ ]*' AUTHORS | sort | uniq | wc -l ) 659 | emails=$( grep -o ' [^ ]* ' AUTHORS | tr -d ' ' | sort | uniq | \ 660 | wc -l ) 661 | sigkeys=$( grep -o '[^ ]*$' AUTHORS | sort | uniq | wc -l ) 662 | if [ "$total" != "$names" ]; then 663 | echo "ERROR: found duplicate names" 1>&2 664 | exit 1 665 | elif [ "$total" != "$emails" ]; then 666 | echo "ERROR: found duplicate emails" 1>&2 667 | exit 1 668 | elif [ "$total" != "$sigkeys" ]; then 669 | echo "ERROR: found duplicate sigkey" 1>&2 670 | exit 1 671 | fi 672 | else 673 | echo "ERROR: unable to find the required AUTHORS file" 1>&2 674 | exit 1 675 | fi 676 | } 677 | 678 | 679 | #---------------tx (transaction) section---------------- 680 | # Functions and handlers related to building, checking, 681 | # and managing transactions. 682 | 683 | # $1 is a parameter 684 | # $2 is a value for $1 685 | build_param_replace_command() { 686 | esc_str=$(echo "$2" | sed "s/\,/\\\\,/g") 687 | echo " | sed 's,<<< $1 >>>,$esc_str,g'" 688 | } 689 | 690 | # $1 is a param to guess 691 | # $2 is a commit hash or HEAD where the tx is described 692 | guess_template_param() { 693 | case $1 in 694 | user_name) 695 | if [ "$2" = "" ] || [ "$2" = "HEAD" ]; then 696 | echo "$USER_NAME" 697 | else 698 | git log -n 1 "$2".. --pretty="%cn" 699 | fi 700 | ;; 701 | user_email) 702 | if [ "$2" = "" ] || [ "$2" = "HEAD" ]; then 703 | echo "$USER_EMAIL" 704 | else 705 | git log -n 1 "$2".. --pretty="%ce" 706 | fi 707 | ;; 708 | user_signingkey) 709 | if [ "$2" = "" ] || [ "$2" = "HEAD" ]; then 710 | echo "$USER_SIGNINGKEY" 711 | else 712 | git log -n 1 "$2".. --pretty="%GK" 713 | fi 714 | ;; 715 | user_height) 716 | if [ "$2" = "" ] || [ "$2" = "HEAD" ]; then 717 | ledger -f ledger/equity.parent bal "$USER_NAME":Height | head -n 1 | grep -o "[^ ][0-9.,]* XP" | tr -d " XP" 718 | else 719 | OTHER_USER=$(git log -n 1 "$2".. --pretty="%cn") 720 | ledger -f ledger/equity.parent bal "$OTHER_USER":Height | head -n 1 | grep -o "[^ ][0-9.,]* XP" | tr -d " XP" 721 | fi 722 | ;; 723 | date) 724 | if [ "$2" = "" ] || [ "$2" = "HEAD" ]; then 725 | date -u +%F 726 | else 727 | date -u +%F --date="@$( git log -n 1 "$2".. --pretty='%ct' )" 728 | fi 729 | ;; 730 | epoch) 731 | if [ "$2" = "" ] || [ "$2" = "HEAD" ]; then 732 | date -u +%s 733 | else 734 | git log -n 1 "$2".. --pretty="%ct" 735 | fi 736 | ;; 737 | vote_parent|parent) 738 | if [ "$2" = "" ]; then 739 | git log -n 1 HEAD --pretty="%H" 740 | else 741 | git log -n 1 "$2" --pretty="%H" 742 | fi 743 | ;; 744 | version) 745 | if [ "$2" = "" ] || [ "$2" = "HEAD" ]; then 746 | if [ -f VERSION ]; then 747 | cat VERSION 748 | else 749 | echo "0.0.1" # default starting version number 750 | fi 751 | else 752 | git show "$2":VERSION 753 | fi 754 | ;; 755 | guild_name) 756 | if [ ! -f GUILD ]; then 757 | # assume we're at initialization phase of personal guild 758 | echo "$USER_NAME" 759 | else # otherwise it must exist and never change! 760 | head -n 1 GUILD | grep -o "[^NAME ].*" 761 | fi 762 | ;; 763 | other_guild) 764 | if [ "$2" = "" ]; then 765 | exit 1 766 | else 767 | gdate=$(guess_template_param 'date' "$2") 768 | grep "$gdate" ledger/transaction.ledger | grep -o "[^ ]*$" 769 | fi 770 | ;; 771 | height) 772 | if [ -d ledger ]; then 773 | GUILD_NAME=guess_template_param "guild_name" 774 | ledger -f ledger/chain.ledger bal "$GUILD_NAME":Height | head -n 1 | grep -o "[^ ][0-9.]* XP" | tr -d " XP" 775 | else 776 | echo 0 777 | fi 778 | ;; 779 | last_transaction) 780 | if [ "$LAST_TRANSACTION" = "" ]; then 781 | grep "LAST_TRANSACTION" GUILD | grep -o "[^ ].*$" 782 | else 783 | echo "$LAST_TRANSACTION" 784 | fi 785 | ;; 786 | patch_path) 787 | grep ".*\; wild_patch:" ledger/transaction.ledger | grep -o "[^ ]*$" 788 | ;; 789 | XGG_amount) 790 | highest=0 791 | IFS="" 792 | # shellcheck disable=SC2013 793 | for line in $(cat ledger/transaction.ledger); do 794 | amt=$( echo "$line" | grep -o "[0-9.] *XGG$" | tr -d "XG " ) 795 | if [ "$(echo "$amt > $highest" | bc)" != "0" ]; then 796 | highest=$amt 797 | fi 798 | done 799 | IFS=$ORIG_IFS 800 | echo "$highest" 801 | ;; 802 | patch_path) 803 | grep ".*\; wild_patch:" ledger/transaction.ledger | grep -o "[^ ]*$" 804 | ;; 805 | XGG_amount) 806 | highest=0 807 | IFS="" 808 | # shellcheck disable=SC2013 809 | for line in $(cat ledger/transaction.ledger); do 810 | amt=$( echo "$line" | grep -o "[0-9.] *XGG$" | tr -d "XG " ) 811 | if [ "$(echo "$amt > $highest" | bc)" != "0" ]; then 812 | highest=$amt 813 | fi 814 | done 815 | IFS=$ORIG_IFS 816 | echo "$highest" 817 | ;; 818 | esac 819 | } 820 | 821 | get_template_params() { 822 | # first argument should be a file or directory to look for templates 823 | if [ -e "$GG_DIR/$1" ]; then 824 | tdir=$GG_DIR/$1 825 | elif [ -d ./template ]; then 826 | # if no argument given, assume current directory is base of repo 827 | tdir=$( readlink -f ./template ) 828 | else 829 | echo "Unable to find template(s) at: ""$1" 1>&2 830 | echo 1>&2 831 | fi 832 | # Find all param tags in file(s), remove brackets, and filter 833 | grep -roh '<<< [a-zA-Z0-9_-.]\{1,80\} >>>' "$tdir" | tr -d '<> ' | sort | uniq 834 | } 835 | 836 | # $1 is the name of the template 837 | # $2 is the revision (default to HEAD) 838 | # $@ are param values to use, as pairs (key=val), preceded by optional flags (--flag) 839 | build_tpl() { 840 | tpl_name="$1" 841 | shift 842 | revision="$1" 843 | shift 844 | reverse="" 845 | if [ "$1" = "--reverse" ]; then 846 | reverse="--reverse" 847 | shift 848 | fi 849 | params=$( get_template_params "$tpl_name" ) 850 | cmd_str="cat $GG_DIR/$tpl_name" 851 | for kv in "$@"; do 852 | key="$(echo "$kv" | grep -o '^[^=]*')" 853 | val="$(echo "$kv" | grep -o '[^=]*$')" 854 | IFS=" " 855 | # shellcheck disable=SC2016 856 | if [ "$(echo "$params" | grep '^"$key"$')" = "" ]; then 857 | cmd_str="$cmd_str $( build_param_replace_command "$key" "$val" )" 858 | params=$(echo "$params" | sed "s,^$key$,,g") 859 | fi 860 | IFS=$ORIG_IFS 861 | done 862 | for p in $params; do 863 | if [ "$p" != "" ]; then 864 | cmd_str="$cmd_str $( build_param_replace_command "$p" "$( guess_template_param "$p" "$revision")" )" 865 | fi 866 | done 867 | if [ "$reverse" = "" ]; then 868 | cmd_str="$cmd_str | patch -s -p2" # TODO what p level to set? 869 | else 870 | cmd_str="$cmd_str | patch -s -R -p2" # TODO what p level to set? 871 | fi 872 | eval "$cmd_str" 873 | } 874 | 875 | list_tx_tags() { 876 | grep tag ledger/tag.ledger | grep -o "[^ ].*$" 877 | } 878 | 879 | # $1 the name of the tag to list templates for 880 | # $2 to reverse the list, set this to "--reverse" 881 | list_tx_tag_templates() { 882 | INTAG=false 883 | if [ "$2" = "--reverse" ]; then 884 | tac ledger/tag.ledger 885 | else 886 | cat ledger/tag.ledger 887 | fi | while read line; do 888 | if [ "$(echo "$line" | grep -E "[\;# ]*[end]{0,3}tag $1")" != "" ]; then 889 | if [ "$INTAG" = "true" ]; then 890 | return 891 | else 892 | INTAG=true 893 | fi 894 | elif [ "$INTAG" = "true" ] && [ "$(echo "$line" | grep \;)" != "" ]; then 895 | echo "$line" | grep -o "[^; ].*$" 896 | fi 897 | done 898 | } 899 | 900 | # $1 to reverse the archive action, set this to "--reverse" 901 | # $2 is an optional commit hash (should always be HEAD or HEAD^) 902 | archive_tx_ledger() { 903 | if [ "$1" = "--reverse" ]; then 904 | if [ "$2" = "HEAD^" ]; then 905 | phash="HEAD^" 906 | fi 907 | # also "unfinishes" the tx by resetting GUILD 908 | rm ledger/equity.parent ledger/equity.ledger ledger/transaction.ledger GUILD 909 | git checkout "$phash" ledger/equity.ledger ledger/equity.parent ledger/transaction.ledger GUILD 910 | ledger_build 911 | else 912 | ledger_build 913 | cp ledger/equity.ledger ledger/equity.parent 914 | echo "" > ledger/transaction.ledger 915 | fi 916 | } 917 | 918 | finish_tx() { 919 | ledger_build 920 | sed -i GUILD -e "s,EPOCH_TIME.*,EPOCH_TIME $(date -u +%s),g" \ 921 | -e "s,LAST_TRANSACTION.*,LAST_TRANSACTION $LAST_TRANSACTION,g" 922 | ledger_equity > ledger/equity.ledger 923 | } 924 | 925 | # $1 is a tag name 926 | # $@ are build tpl params or flags with no '=' (i.e. --reverse) 927 | build_tx() { 928 | export LAST_TRANSACTION="$1" 929 | shift 930 | reverse="" 931 | phash="HEAD" 932 | if [ "$1" = "--reverse" ]; then 933 | reverse="--reverse" 934 | shift 935 | if [ "$(git status --short)" = "" ]; then 936 | phash="HEAD^" 937 | fi 938 | else 939 | archive_tx_ledger 940 | fi 941 | list_tx_tag_templates "$LAST_TRANSACTION" "$reverse" | while read tpl; do 942 | if [ "$( echo "$tpl" | grep '^patch .*patch$' )" != "" ]; then 943 | ptpl="$( echo "$tpl" | grep -o '[^ ]*$' )" 944 | build_tpl "$ptpl" "$phash" "$reverse" "$@" 945 | elif [ "$( echo "$tpl" | grep '^wild_patch' )" != "" ]; then 946 | # fild patch_path from transaction tag 947 | patch_path=$(grep ".*\; wild_patch:" ledger/transaction.ledger | grep -o "[^ ]*$") 948 | build_tpl "$patch_path" "$phash" "$reverse" "$@" 949 | fi 950 | done 951 | if [ "$reverse" = "" ]; then 952 | finish_tx 953 | else 954 | archive_tx_ledger "$reverse" "$phash" 955 | fi 956 | } 957 | 958 | # $1 is the parent commit to check against (default HEAD, then HEAD^) 959 | check_tx() { 960 | if [ "$1" = "" ]; then 961 | wdelta=$(git status --short) 962 | if [ "$wdelta" = "" ]; then 963 | phash="HEAD^" 964 | else 965 | phash="HEAD" 966 | git stash --keep-index 967 | fi 968 | else 969 | phash="$1" 970 | git checkout "$phash" || exit 1 971 | fi 972 | # if committed, check signer 973 | if [ "$phash" != "HEAD" ]; then 974 | sigkey="$(git log "$phash^..$phash" --pretty="%GK" | grep -o '.\{8\}$')" 975 | if [ "$sigkey" = "" ]; then 976 | echo "No gpg signature found for tx at $1" 1>&2 977 | exit 1 978 | fi 979 | signer=$(grep " $sigkey$" ./AUTHORS) 980 | if [ "$signer" = "" ]; then 981 | echo "Signer $signer is not known to this guild." 1>&2 982 | exit 1 983 | fi 984 | fi 985 | gdata=$(cat GUILD) 986 | #parent_gdata=$(git show "$phash":GUILD) 987 | # lookup last tx in GUILD 988 | last_tx=$(echo "$gdata" | grep "LAST_TRANSACTION" | grep -o "[^ ]*$") 989 | # ensure equity.parent is same as parent's equity.ledger 990 | parent_equity="$(git show "$phash":ledger/equity.ledger)" 991 | equity_parent="$(cat ledger/equity.parent)" 992 | if [ "$parent_equity" != "$equity_parent" ]; then 993 | #echo "$parent_equity" 1>&2 994 | #echo "$equity_parent" 1>&2 995 | echo "Equity of parent was not used for this commit" 1>&2 996 | exit 1 997 | fi 998 | # ensure height increased 999 | height=$(ledger -f ledger/equity.ledger bal "$GUILD_NAME:Height:$GUILD_NAME" | head -n 1 | grep -o "[0-9.]* *XP" | tr -d "XP ") 1000 | parent_height=$(ledger -f ledger/equity.parent bal "$GUILD_NAME:Height:$GUILD_NAME" | head -n 1 | grep -o "[0-9.]* *XP" | tr -d "XP ") 1001 | if [ "$(echo "$height > $parent_height" | bc)" = "0" ]; then 1002 | echo "Height $height not greater than parent $parent_height" 1>&2 1003 | exit 1 1004 | fi 1005 | tpl_list=$(list_tx_tag_templates "$last_tx") 1006 | if [ "$tpl_list" = "" ]; then 1007 | echo "Last transaction tag $last_tx is unknown" 1>&2 1008 | exit 1 1009 | fi 1010 | # ensure tag instructions were followed 1011 | # ensure output matches exactly 1012 | build_tx "$last_tx" --reverse 1013 | git diff "$phash" 1014 | if [ "$(git diff "$phash")" != "" ]; then 1015 | echo "Reverse tx build of $last_tx failed." 1>&2 1016 | exit 1 1017 | fi 1018 | if [ "$phash" = "HEAD" ]; then 1019 | git stash apply 1020 | else 1021 | git reset --hard HEAD 1022 | fi 1023 | } 1024 | 1025 | 1026 | # create patch, preserving some privacy, and the LICENSE 1027 | # $1 the before file or directory (default clean HEAD) 1028 | # $2 the after file or directory (default any uncommitted changes in pwd) 1029 | create_patch() { 1030 | INPATH=$1 1031 | OUTPATH=$2 1032 | if [ "$1" = "" ]; then 1033 | rm -fR "$GG_DIR/tmp" 1034 | mkdir "$GG_DIR/tmp" 1035 | cp -fR ./.git "$GG_DIR/tmp"/ 1036 | cp -fR ./* "$GG_DIR/tmp"/ 1037 | OLD_TOO_MANY_DIRS=$( pwd ) 1038 | cd "$GG_DIR/tmp" 1039 | _=$( git clean -f ) 1040 | _=$( git reset --hard HEAD ) 1041 | cd "$OLD_TOO_MANY_DIRS" 1042 | INPATH="$GG_DIR/tmp" 1043 | fi 1044 | if [ "$2" = "" ]; then 1045 | OUTPATH="$( readlink -f . )" 1046 | fi 1047 | # each patch should start with the license 1048 | if [ -f "./LICENSE" ]; then 1049 | sed 's/^/#/' ./LICENSE 1050 | echo "#" 1051 | echo 1052 | fi 1053 | diff -cr -N "$INPATH" "$OUTPATH" -x .git -x .\*template/\*.patch -x \*generated_check.ledger | sed "s,$INPATH,/old/,g" | sed "s,$OUTPATH,/new/,g" 1054 | } 1055 | 1056 | # $1 remote name to check 1057 | use_gitolite_push() { 1058 | if [ "$( git remote get-url "$1" | grep \"file://\")" != "" ] && [ "$USE_GITOLITE" = "true" ]; then 1059 | echo 1 1060 | else 1061 | echo 0 1062 | fi 1063 | } 1064 | 1065 | ### pull 1066 | gg_pull() { 1067 | git pull "$USER_NAME" 1068 | } 1069 | 1070 | #-----------------------ledger section--------------------------- 1071 | 1072 | # print the equity splitting confirmed and unconfirmed 1073 | ledger_equity() { 1074 | if [ -f ledger/transaction.ledger ]; then 1075 | ledger -C -f ledger/chain.ledger equity | sed 's/ Opening Balances/ * Cleared Balances/g' 1076 | ledger -U -f ledger/chain.ledger equity | sed 's/Opening Balances/Uncleared Balances/g' 1077 | fi 1078 | } 1079 | 1080 | # $1 the account prefix (check or assert) 1081 | # $2 an account line from ledger 1082 | generate_checks_from_accounts() { 1083 | IFS=":" 1084 | level="0" 1085 | user="" 1086 | guild="" 1087 | branch="" 1088 | top="" 1089 | for account in $2; do 1090 | # shellcheck disable=SC2003 1091 | level=$(expr "$level" + 1) 1092 | case $level in 1093 | 1) 1094 | user="$account" 1095 | echo "assert user_vote_check(\"$user\")" 1096 | ;; 1097 | # skip 2, as no checks to run 1098 | 3) 1099 | guild="$account" 1100 | ;; 1101 | 4) 1102 | branch="$account" 1103 | echo "assert branch_vote_check(\"$user\", \"$guild\", \"$branch\" ) " 1104 | ;; 1105 | 5) 1106 | top="$account" 1107 | echo "assert user_issue_vote_check(\"$user\", \"$guild\", \"$branch\", \"$top\")" 1108 | IFS=$ORIG_IFS 1109 | return 1110 | ;; 1111 | esac 1112 | done 1113 | IFS=$ORIG_IFS 1114 | } 1115 | 1116 | # build local ledger files for running (i.e. generate check file) 1117 | ledger_build() { 1118 | ACCT_PREFIX="assert" 1119 | while read line 1120 | do 1121 | if [ "$(echo "$line" | grep '^#')" != "" ]; then 1122 | continue 1123 | elif [ "$(echo "$line" | grep '\* Cleared Balances')" != "" ]; then 1124 | ACCT_PREFIX="assert" 1125 | elif [ "$(echo "$line" | grep ' Uncleared Balances')" != "" ]; then 1126 | ACCT_PREFIX="check" 1127 | elif [ "$line" != "" ]; then 1128 | acline="$(echo "$line" | grep -o '^ *[0-9a-zA-Z:]*' | tr -d ' ')" 1129 | generate_checks_from_accounts "$ACCT_PREFIX" "$acline" 1130 | if [ "$(grep "$acline" ledger/transaction.ledger )" != "" ]; then 1131 | grep \; ledger/transaction.ledger | grep -o "[^ ]*$" | while read txl 1132 | do 1133 | if [ "$(grep "$txl" ledger/tag.ledger)" != "" ]; then 1134 | min_votes=$(list_tx_tag_templates "$txl" | grep min_votes | grep -o '[^ ]*$') 1135 | if [ "$min_votes" != "" ]; then 1136 | echo "$ACCT_PREFIX issue_vote_check(\"$user\", \"$guild\", \"$branch\", \"$top\", $min_votes XP)" 1137 | fi 1138 | fi 1139 | done 1140 | fi 1141 | fi 1142 | done < ledger/equity.ledger | sort | uniq > ledger/generated_check.ledger 1143 | } 1144 | 1145 | __main "$@" 1146 | 1147 | -------------------------------------------------------------------------------- /h/pre-commit-gg-only: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | shellcheck gitguild || exit 1 4 | shellcheck configure || exit 1 5 | shellcheck t/*.sh || exit 1 6 | # capture stdout but print stderr 7 | _=$(ledger -f ledger/chain.ledger bal) || exit 1 8 | 9 | -------------------------------------------------------------------------------- /keydir/gitguild.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCppeWmGWxf97SCmPgnajSTGcwWmdK1eVTQDzrYSTAfUE9b8WO6QQ5aX/pf//NDW80AZxLsPlOeBzX0f644VWzAeetJU/kWaloQRWT8m5Fq3+jNlqBHbirTjCeysO8glkdSJq4W7PYJSAF/9R1N1hNcYStVXjB+d6ey6e8jhtMcEcQh+ZqchgoSLx7ZPxIXggcSaAsQyPWxdQFUFEy0RFy/3wM+ku9g37YaKFMeXhPtmc22eN4M5cof0J0jmffoEvvKACRp6PTSI38WtwjX5Tn2hTG75Uf3vNPkpfY36aG5QWvraQ3O1h5g+rrWXhw9YXn0FEW2BI3otk5qIFsd39NOT/rrBDox7wNTVN3FQK7sJlnOtau1FWxPWP+TpuCe1UhB7fn1yhgFpAl9+q6LYKJPp7igKe5/sh9FwHZjNoL84tIY36xKzrgS30gW65kpNwreu7Yg0p4+aEj+inHXcrUb8kSVLmwXmIrdtN+gzbEWsaJ9bIv1csZYRNL2GImrtTEZIhOGt8suTN0k/A56egkYpU237sd73lOTejURqP89xHC4vNCclz4ggXL32CDmW6cU0LcZ3XmBUPZHodgiNY9SOxo/mfdVjaxPXrfUddjMtg3TsG1qdy74A6ls1zwH+hhSH4g3HCGqc3pLW8/49M9Qd8aTjqZxRwbTKODWTWoc5w== SER_EMAIL -f /home/gitguild/.ssh/gitguild 2 | -------------------------------------------------------------------------------- /keydir/isysd.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDnOb1R3uI6iwtk6WbR3J2bwvmvOtKOosPxpZ84RnHcFQCGKQ8JfIAPouRxcG4mlenlPFnBGnH5VE6W2c31quEa05UEohHmaVV/d+H9S8uvyg6SupYoCP9fq2Gd7a1vDRQ/1witS05QvbnsTziaBGhUQ0U6/k/R1QN0eykekxwFEPZHw8O1Iy3cu70lgse1Mzo9lcIp/XbEHmg86n2U+GsOTEf1j6mKstJP55Tni+NwDGGL1nfZ02WQ9Pgh6djnI9DBhLTS29fOFAtkEnxlcagPW92UOzg3u7wqd1PSRkGzU+KlcWSwBf8372sPWmlec/SQeGGGg76v8/XcM4hLzuiD ira@gitguild.com 2 | -------------------------------------------------------------------------------- /ledger/account.ledger: -------------------------------------------------------------------------------- 1 | ; Account structure is quite complex in the GitGuild, creating a symmetry between this ledger and the git tree itself. 2 | ; A number of complex and potentially long account names may be difficult to read, but they're quite organized. 3 | ; The basic structure is as follows. 4 | ; 5 | ; username:user account:repository:branch:parent commit hash:metadata 6 | ; 7 | ; Most of these are probably self explanatory. User account is the usual suspects of accounting: Income, Expenses, Assets, Liabilities, Equity. 8 | ; User account also has two additional options related to voting: Height, Depth. 9 | ; Metadata might be bitcoin or dash addresses, and/or transaction hashes. 10 | 11 | account gitguild 12 | note The GitGuild's main account. 13 | 14 | ; Consensus accounts, for voting. 15 | account gitguild:Depth 16 | note the Guild's voting account. XP originates here, given out by the guild to deserving members, corresponding to XGG income earned. 17 | assert commodity == "XP" 18 | account gitguild:Height 19 | note the Guild's vote counting area. Votes by members on commits related to this guild are recorded here. 20 | assert commodity == "XP" 21 | 22 | ; Normal accounting categories. Each guild/user has these. 23 | account gitguild:Expenses 24 | note The Guild's Expenses, i.e. Asset redemptions, contribution pay origination 25 | account gitguild:Equity 26 | account gitguild:Income 27 | note The Guild's Income, i.e. Sponsorships, revenues 28 | account gitguild:Assets 29 | note The Guild's Assets, available for member redeption as part of earned Income tx, i.e. contribution 30 | account gitguild:Liabilities 31 | 32 | account isysd:Height 33 | account isysd:Depth 34 | account isysd:Expenses 35 | account isysd:Equity 36 | account isysd:Income 37 | account isysd:Assets 38 | account isysd:Liabilities 39 | -------------------------------------------------------------------------------- /ledger/chain.ledger: -------------------------------------------------------------------------------- 1 | !include commodity.ledger 2 | !include account.ledger 3 | !include tag.ledger 4 | !include equity.parent 5 | !include transaction.ledger 6 | !include check.ledger 7 | !include generated_check.ledger 8 | -------------------------------------------------------------------------------- /ledger/check.ledger: -------------------------------------------------------------------------------- 1 | define GUILD_DEPTH = (-account("gitguild:Depth:gitguild").total) 2 | define GUILD_HEIGHT = (account("gitguild:Height:gitguild").total) 3 | 4 | ; Each user must have net positive score 5 | define user_vote_check(user_name) = (account(user_name + ":Height").total >= 0 XP) 6 | 7 | ; Each branch of this guild must have net positive score 8 | define branch_vote_check(user_name, vote_guild_name, vote_branch) = (account(user_name + ":Height:" + vote_guild_name + ":" + vote_branch).total >= 0) 9 | 10 | ; Each issue must have score higher than given in the tag 11 | define issue_vote_check(user_name, vote_guild_name, vote_branch, vote_parent, min_votes) = (account(user_name + ":Height:" + vote_guild_name + ":" + vote_branch + ":" + vote_parent).total >= GUILD_DEPTH * min_votes) 12 | 13 | ; user has not spent more XP than allowed on this issue 14 | define user_issue_vote_check(user_name, vote_guild_name, vote_branch, vote_parent) = (account(user_name + ":Height").total >= abs(account(user_name + ":Depth:" + vote_guild_name + ":" + vote_branch + ":" + vote_parent).total)) 15 | 16 | -------------------------------------------------------------------------------- /ledger/commodity.ledger: -------------------------------------------------------------------------------- 1 | commodity XP 2 | note Experience Points, used for voting on members and issues 3 | format 1,000.00 XP 4 | nomarket 5 | 6 | commodity XGG 7 | note GitGuild token of value. Transferable and redeemable at bid rate if part of approved Income transaction. 8 | format 1,000.0000 XGG 9 | ; governor gitguild 10 | 11 | commodity DASH 12 | note See dash.org 13 | format 1,000.00000000 DASH 14 | nomarket 15 | 16 | commodity BTC 17 | note See bitcoin.org 18 | format 1,000.00000000 BTC 19 | nomarket 20 | -------------------------------------------------------------------------------- /ledger/equity.ledger: -------------------------------------------------------------------------------- 1 | 2016/12/27 * Cleared Balances 2 | gitguild:Depth:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 -1,000.00 XP 3 | gitguild:Expenses:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 1,000.0000 XGG 4 | gitguild:Height:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 1,000.00 XP 5 | gitguild:Liabilities:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 -1,000.0000 XGG 6 | isysd:Assets:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 -1,000.0000 XGG 7 | isysd:Depth:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 -1,000.00 XP 8 | isysd:Height:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 1,000.00 XP 9 | isysd:Income:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 1,000.0000 XGG 10 | 2017/01/01 Uncleared Balances 11 | gitguild:Depth:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da -10.00 XP 12 | gitguild:Expenses:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da 10.0000 XGG 13 | gitguild:Height:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da 1,000.00 XP 14 | gitguild:Liabilities:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da -10.0000 XGG 15 | isysd:Assets:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da 10.0000 XGG 16 | isysd:Depth:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da -1,000.00 XP 17 | isysd:Height:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da 10.00 XP 18 | isysd:Income:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da -10.0000 XGG 19 | -------------------------------------------------------------------------------- /ledger/equity.parent: -------------------------------------------------------------------------------- 1 | 2016/12/27 * Cleared Balances 2 | gitguild:Depth:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 -1,000.00 XP 3 | gitguild:Expenses:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 1,000.0000 XGG 4 | gitguild:Height:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 1,000.00 XP 5 | gitguild:Liabilities:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 -1,000.0000 XGG 6 | isysd:Assets:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 1,000.0000 XGG 7 | isysd:Depth:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 -1,000.00 XP 8 | isysd:Height:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 1,000.00 XP 9 | isysd:Income:gitguild:isysd:172209b109dd42cc53ce3556b929dde7a21134b6 -1,000.0000 XGG 10 | -------------------------------------------------------------------------------- /ledger/tag.ledger: -------------------------------------------------------------------------------- 1 | tag init_personal 2 | ; patch gitguild/template/clean_gitolite_admin.patch 3 | ; patch gitguild/template/add_member_authors.patch 4 | ; patch gitguild/template/add_general_project_files.patch 5 | ; patch gitguild/template/add_ledger_basics.patch 6 | ; patch gitguild/template/personal_ledger_init.patch 7 | ; patch gitguild/template/add_GUILD.patch 8 | ; min_votes 0 9 | ; endtag init_personal 10 | 11 | tag register_member 12 | ; patch gitguild/template/add_member_authors.patch 13 | ; patch gitguild/template/add_member_ledger.patch 14 | ; patch gitguild/template/add_member_gitolite.patch 15 | ; min_votes 0 16 | ; endtag register_member 17 | 18 | tag fork_repo 19 | ; patch gitguild/template/fork_repo.patch 20 | ; min_votes 0.5 21 | ; endtag fork_repo 22 | 23 | tag register_personal_gitguild 24 | ; patch gitguild/template/add_member_authors.patch 25 | ; patch gitguild/template/register_personal_gitguild_ledger.patch 26 | ; min_votes 0.66 27 | ; endtag register_personal_gitguild 28 | 29 | tag contribute 30 | ; patch gitguild/template/contribute.patch 31 | ; min_votes 0.66 32 | ; wild_patch 33 | ; endtag contribute 34 | 35 | tag paid_contribution 36 | ; patch gitguild/template/paid_contribution.patch 37 | ; min_votes 0.75 38 | ; wild_patch 39 | ; endtag paid_contribution 40 | 41 | tag wild_patch 42 | check value =~ /.*template.*.patch$/ 43 | ; min_votes 0.66 44 | ; endtag patch 45 | 46 | -------------------------------------------------------------------------------- /ledger/transaction.ledger: -------------------------------------------------------------------------------- 1 | 2017-01-01 Paid Contribution 2 | ; paid_contribution 3 | ; wild_patch: gitguild/template/isysd_contribution_1.patch 4 | isysd:Income:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da -10 XGG 5 | isysd:Assets:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da 10 XGG 6 | gitguild:Liabilities:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da -10 XGG 7 | gitguild:Expenses:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da 10 XGG 8 | isysd:Height:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da 10 XP 9 | isysd:Depth:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da -1,000.00 XP 10 | gitguild:Height:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da 1,000.00 XP 11 | gitguild:Depth:gitguild:isysd:065f27084234d02358d820c6e069d474f98de6da -10 XP 12 | 13 | -------------------------------------------------------------------------------- /t/helpers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export USER_NAME=$( git config user.name ) 3 | export USER_EMAIL=$( git config user.email ) 4 | export USER_SIGNINGKEY=$( git config user.signingkey ) 5 | 6 | # $1 failure message 7 | fail() { 8 | echo "FAIL: $1" 1>&2 9 | teardown 10 | exit 1 11 | } 12 | 13 | basics_exist() { 14 | if [ ! -d "$HOME/gitguild" ]; then 15 | fail "$HOME/gitguild does not exist" 16 | elif [ ! -d "$HOME/gitguild/$USER_NAME" ]; then 17 | fail "$HOME/gitguild/$USER_NAME" 18 | elif [ ! -d "$HOME"/gitguild/gitguild ]; then 19 | fail "$HOME/gitguild/gitguild does not exist" 20 | fi 21 | wpath=$( which gitguild ) 22 | if [ "$wpath" = "" ]; then 23 | fail "gitguild not found in PATH" 24 | fi 25 | } 26 | 27 | gitolite_installed() { 28 | wpath=$( which gitolite ) 29 | if [ "$wpath" = "" ] && [ "$USE_GITOLITE" = "true" ]; then 30 | fail "gitolite not found in PATH" 31 | elif [ "$wpath" != "" ] && [ "$USE_GITOLITE" = "false" ]; then 32 | fail "gitolite unexpectedly found in PATH" 33 | fi 34 | if [ ! -d "$HOME"/repositories ] && [ "$USE_GITOLITE" = "true" ]; then 35 | fail "$HOME/repositories not found" 36 | elif [ -d "$HOME"/repositories ] && [ "$USE_GITOLITE" = "false" ]; then 37 | fail "$HOME/repositories unexpectedly exists" 38 | fi 39 | if [ -d "$HOME"/repositories/gitolite-admin.git ]; then 40 | fail "$HOME/repositories/gitolite-admin.git unexpectedly exists" 41 | fi 42 | if [ ! -d "$HOME/repositories/$USER_NAME.git" ]; then 43 | fail "$HOME/repositories/$USER_NAME.git not found" 44 | fi 45 | } 46 | 47 | oksh_installed() { 48 | wpath=$( which ok.sh ) 49 | if [ "$wpath" = "" ] && [ "$USE_GITHUB" = "true" ]; then 50 | fail "ok.sh not found in PATH" 51 | elif [ "$wpath" != "" ] && [ "$USE_GITHUB" = "false" ]; then 52 | fail "ok.sh unexpectedly found in PATH" 53 | fi 54 | if [ ! -d "$HOME"/gitguild/ok.sh ] && [ "$USE_GITHUB" = "true" ]; then 55 | fail "$HOME/gitguild/ok.sh not found" 56 | elif [ -d "$HOME"/gitguild/ok.sh ] && [ "$USE_GITHUB" = "false" ]; then 57 | fail "$HOME/gitguild/ok.sh unexpectedly exists" 58 | fi 59 | } 60 | 61 | personal_guild_initialized() { 62 | if [ ! -d "$HOME/gitguild/$USER_NAME/ledger" ]; then 63 | fail "$HOME/gitguild/$USER_NAME/ledger not found" 64 | elif [ ! -d "$HOME/gitguild/$USER_NAME/conf" ]; then 65 | fail "$HOME/gitguild/$USER_NAME/conf not found" 66 | elif [ ! -d "$HOME/gitguild/$USER_NAME/keydir" ]; then 67 | fail "$HOME/gitguild/$USER_NAME/keydir not found" 68 | elif [ ! -f "$HOME/gitguild/$USER_NAME/keydir/$USER_NAME.pub" ]; then 69 | fail "$HOME/gitguild/$USER_NAME/keydir/$USER_NAME.pub not found" 70 | elif [ ! -f "$HOME/gitguild/$USER_NAME/AUTHORS" ]; then 71 | fail "$HOME/gitguild/$USER_NAME/AUTHORS not found" 72 | elif [ ! -f "$HOME/gitguild/$USER_NAME/GUILD" ]; then 73 | fail "$HOME/gitguild/$USER_NAME/GUILD not found" 74 | elif [ ! -f "$HOME/gitguild/$USER_NAME/VERSION" ]; then 75 | fail "$HOME/gitguild/$USER_NAME/VERSION not found" 76 | elif [ ! -f "$HOME/gitguild/$USER_NAME/CONTRIBUTING.md" ]; then 77 | fail "$HOME/gitguild/$USER_NAME/CONTRIBUTING.md not found" 78 | elif [ ! -f "$HOME/gitguild/$USER_NAME/CHANGELOG.md" ]; then 79 | fail "$HOME/gitguild/$USER_NAME/CHANGELOG.md not found" 80 | fi 81 | } 82 | 83 | -------------------------------------------------------------------------------- /t/run_tests.sh: -------------------------------------------------------------------------------- 1 | tests=$( find ./ -name "test_*.sh" ) 2 | 3 | execute_all() { 4 | for t in $tests; do 5 | ./"$t" 6 | done 7 | } 8 | 9 | execute_install() { 10 | echo "----------------This installation test is dangerous!--------------------" 11 | echo "It will wipe any local gitguild data, and also move around PGP and SSH keys! Are you sure you want to run it?" 12 | read readyono 13 | echo 14 | if [ "$( echo "$readyono" | grep '[yY].*' )" != "" ]; then 15 | . "./unsafe_install_test.sh" 16 | fi 17 | } 18 | 19 | case "$1" in 20 | install) 21 | execute_install 22 | ;; 23 | *) 24 | execute_all 25 | esac 26 | 27 | -------------------------------------------------------------------------------- /t/test_tx_engine.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "./helpers.sh" 3 | 4 | teardown() { 5 | rm -fR "$HOME/gitguild/tmp" 6 | } 7 | 8 | setup() { 9 | rm -fR "$HOME/gitguild/tmp" 10 | cp -fR "$HOME/gitguild/$USER_NAME" "$HOME/gitguild/tmp" 11 | cd "$HOME/gitguild/tmp" 12 | if [ "$(pwd)" = "$HOME/gitguild/tmp" ]; then 13 | git reset --hard HEAD || exit 1 14 | else 15 | fail "Could not create test env at $HOME/gitguild/tmp" 16 | exit 1 17 | fi 18 | } 19 | 20 | __main() { 21 | setup 22 | # the last transaction should be valid. check to make sure... 23 | gitguild tx check 24 | if [ "$?" != 0 ]; then 25 | fail "Last transaction was not valid. Cannot run tx tests." 26 | teardown 27 | exit 1 28 | fi 29 | echo "OK, ready for tests" 30 | # build a new tx but don't commit 31 | gitguild tx build fork_repo other_guild=fakeguildnoexiste 32 | gitguild tx check 33 | if [ "$?" != 0 ]; then 34 | fail "Working transaction check failed." 35 | teardown 36 | exit 1 37 | fi 38 | # now commit and check again 39 | git commit -m "test fork" 40 | gitguild tx check 41 | if [ "$?" != 0 ]; then 42 | fail "Working transaction check failed." 43 | teardown 44 | exit 1 45 | fi 46 | } 47 | 48 | __main "$@" 49 | 50 | -------------------------------------------------------------------------------- /t/unsafe_install_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "./helpers.sh" 3 | export USE_GITOLITE=false 4 | export USE_GITHUB=false 5 | 6 | teardown() { 7 | # move any ssh keys back to original locations 8 | if [ -f "$HOME/.ssh/$USER_NAME.pub.bak" ]; then 9 | mv "$HOME/.ssh/$USER_NAME.bak" "$HOME/.ssh/$USER_NAME" 10 | mv "$HOME/.ssh/$USER_NAME.pub.bak" "$HOME/.ssh/$USER_NAME.pub" 11 | fi 12 | #if [ -f "$HOME/.ssh/id_rsa.pub.bak" ]; then 13 | # mv "$HOME/.ssh/id_rsa.bak" "$HOME/.ssh/id_rsa" 14 | # mv "$HOME/.ssh/id_rsa.pub.bak" "$HOME/.ssh/id_rsa.pub" 15 | #fi 16 | git config --global --add user.name "$USER_NAME" 17 | git config --global --add user.email "$USER_EMAIL" 18 | git config --global --add user.signingkey "$USER_SIGNINGKEY" 19 | } 20 | 21 | setup() { 22 | # unset user to simulate unconfigured git 23 | git config --global --unset-all user.name 24 | git config --global --unset-all user.email 25 | git config --global --unset-all user.signingkey 26 | # clean up any existing installation 27 | make -s uninstall 28 | # back up ssh keys and move out of proper place 29 | if [ -f "$HOME/.ssh/$USER_NAME.pub" ]; then 30 | mv "$HOME/.ssh/$USER_NAME" "$HOME/.ssh/$USER_NAME.bak" 31 | mv "$HOME/.ssh/$USER_NAME.pub" "$HOME/.ssh/$USER_NAME.pub.bak" 32 | fi 33 | #if [ -f "$HOME/.ssh/id_rsa.pub" ]; then 34 | # mv "$HOME/.ssh/id_rsa" "$HOME/.ssh/id_rsa.bak" 35 | # mv "$HOME/.ssh/id_rsa.pub" "$HOME/.ssh/id_rsa.pub.bak" 36 | #fi 37 | } 38 | 39 | __main() { 40 | # back to base dir 41 | if [ ! -f "./configure" ]; then 42 | cd ../ 43 | fi 44 | # basic configure, no options, only good gpg key 45 | setup 46 | git config --global --add user.signingkey "$USER_SIGNINGKEY" 47 | #echo "if you get to the gpg --gen-key prompt, type ctrl+d" 48 | # shellcheck disable=SC2028 49 | mess=$( echo "$USER_NAME""_bad\n""$USER_EMAIL""_bad\n" | ./configure ) 50 | if [ "$( echo "$mess" | grep 'WARNING: Git user.name not configured.' )" = "" ]; then 51 | fail "git user configuration prompt not triggered" 52 | elif [ "$( echo "$mess" | grep 'WARNING: Git user.email not configured.' )" = "" ]; then 53 | fail "git user configuration prompt not triggered" 54 | # elif [ "$( echo "$mess" | grep 'guessing' )" != "" ]; then 55 | # fail "git user configuration guessing unexpectedly triggered" 56 | elif [ "$( echo "$mess" | grep ".*Operating as user.*$USER_NAME_bad.*$USER_EMAIL_bad.*$USER_SIGNINGKEY" )" = "" ]; then 57 | fail "git user configuration not successful" 58 | fi 59 | teardown 60 | echo "basic configuration, no options, only good gpg key passed." 61 | 62 | # basic configure, no options, in AUTHORS, only known username 63 | setup 64 | mess=$( echo "$USER_NAME" | ./configure ) 65 | if [ "$( echo "$mess" | grep 'WARNING: Git user.name not configured.' )" = "" ]; then 66 | fail "git user configuration prompt not triggered" 67 | elif [ "$( echo "$mess" | grep 'WARNING: Git user.email not configured.' )" = "" ]; then 68 | fail "git user configuration prompt not triggered" 69 | elif [ "$( echo "$mess" | grep 'guessing' )" = "" ]; then 70 | fail "git user configuration guessing not triggered" 71 | elif [ "$( echo "$mess" | grep ".*Operating as user.*$USER_NAME.*$USER_EMAIL.*$USER_SIGNINGKEY" )" = "" ]; then 72 | fail "git user configuration guessing not successful" 73 | fi 74 | teardown 75 | echo "basic configuration known username in AUTHORS passed." 76 | 77 | # basic install, use gitolite 78 | USE_GITOLITE=true 79 | setup 80 | git config --global --add user.name "$USER_NAME" 81 | _=$( ./configure ) 82 | make -s "install" 83 | basics_exist 84 | gitolite_installed 85 | oksh_installed 86 | personal_guild_initialized 87 | teardown 88 | echo "basic install, use gitolite passed" 89 | 90 | # basic install, use gitolite and github 91 | USE_GITHUB=true 92 | setup 93 | git config --global --add user.name "$USER_NAME" 94 | _=$( ./configure ) 95 | make -s "install" 96 | basics_exist 97 | gitolite_installed 98 | oksh_installed 99 | personal_guild_initialized 100 | teardown 101 | echo "basic install, use gitolite and github passed" 102 | } 103 | 104 | __main "$@" 105 | 106 | -------------------------------------------------------------------------------- /template/add_GUILD.patch: -------------------------------------------------------------------------------- 1 | diff -cr -N -x .git -x '*.patch' /old//GUILD /new//GUILD 2 | *** /old//GUILD 1969-12-31 19:00:00.000000000 -0500 3 | --- /new//GUILD 2016-12-24 08:12:25.989834640 -0500 4 | *************** 5 | *** 0 **** 6 | --- 1,4 ---- 7 | + NAME <<< guild_name >>> 8 | + LAST_TRANSACTION <<< last_transaction >>> 9 | + EPOCH_TIME <<< epoch >>> 10 | + 11 | -------------------------------------------------------------------------------- /template/add_general_project_files.patch: -------------------------------------------------------------------------------- 1 | diff -cr -N -x .git -x '*.patch' /old//.gitignore /new//.gitignore 2 | *** /old//.gitignore 2016-12-23 16:00:00.000000000 -0500 3 | --- /new//.gitignore 2016-12-23 16:31:48.615752000 -0500 4 | *************** 5 | *** 0 **** 6 | --- 1 ---- 7 | + ledger/generated_check.ledger 8 | diff -cr -N -x .git -x '*.patch' /old//CHANGELOG.md /new//CHANGELOG.md 9 | *** /old//CHANGELOG.md 1969-12-31 19:00:00.000000000 -0500 10 | --- /new//CHANGELOG.md 2016-12-23 16:31:48.615752000 -0500 11 | *************** 12 | *** 0 **** 13 | --- 1,16 ---- 14 | + # Change Log 15 | + 16 | + All notable changes to this project will be documented in this file. 17 | + This project adheres to [Semantic Versioning](http://semver.org/). 18 | + 19 | + This Change Log format is suggested by 20 | + 21 | + 22 | + 23 | + ## <<< version >>> (<<< date >>>) 24 | + 25 | + #### Added 26 | + 27 | + * Install and configure gitguild 28 | + * Ledger for this guild 29 | + * <<< user_name >>> becomes member 30 | \ No newline at end of file 31 | diff -cr -N -x .git -x '*.patch' /old//CONTRIBUTING.md /new//CONTRIBUTING.md 32 | *** /old//CONTRIBUTING.md 1969-12-31 19:00:00.000000000 -0500 33 | --- /new//CONTRIBUTING.md 2016-12-21 19:15:05.011980000 -0500 34 | *************** 35 | *** 0 **** 36 | --- 1,3 ---- 37 | + # A GitGuild Project 38 | + 39 | + This project uses [GitGuild](https://github.com/GitGuild/gitguild-cli) software to govern itself and all contributions. Please install the client to ensure you meet the strict configuration and usage requirements. 40 | diff -cr -N -x .git -x '*.patch' /old//README.md /new//README.md 41 | *** /old//README.md 1969-12-31 19:00:00.000000000 -0500 42 | --- /new//README.md 2016-12-23 16:35:42.051748000 -0500 43 | *************** 44 | *** 0 **** 45 | --- 1,3 ---- 46 | + # <<< guild_name >>> 47 | + 48 | + This document should provide an introduction to your guild/project for the first time visitor. 49 | \ No newline at end of file 50 | diff -cr -N -x .git -x '*.patch' /old//VERSION /new//VERSION 51 | *** /old//VERSION 1969-12-31 19:00:00.000000000 -0500 52 | --- /new//VERSION 2016-12-22 11:36:33.260868000 -0500 53 | *************** 54 | *** 0 **** 55 | --- 1 ---- 56 | + <<< version >>> 57 | -------------------------------------------------------------------------------- /template/add_member_authors.patch: -------------------------------------------------------------------------------- 1 | diff -cr -N -x .git -x '*.patch' /old//AUTHORS /new//AUTHORS 2 | *** /old//AUTHORS 1969-12-31 19:00:00.000000000 -0500 3 | --- /new//AUTHORS 2016-12-23 11:00:15.859360525 -0500 4 | *************** 5 | *** 0 **** 6 | --- 1 ---- 7 | + <<< user_name >>> <<< user_email >>> <<< user_signingkey >>> 8 | -------------------------------------------------------------------------------- /template/clean_gitolite_admin.patch: -------------------------------------------------------------------------------- 1 | diff -cr -N -x .git -x '*.patch' /old//conf/gitolite.conf /new//conf/gitolite.conf 2 | *** /old//conf/gitolite.conf 2016-12-23 10:57:00.243364028 -0500 3 | --- /new//conf/gitolite.conf 2016-12-23 10:56:21.707364718 -0500 4 | *************** 5 | *** 1,5 **** 6 | repo <<< guild_name >>> 7 | - RW+ = <<< guild_name >>> 8 | 9 | - repo testing 10 | - RW+ = @all 11 | --- 1,6 ---- 12 | + repo @all 13 | + RW refs/.* = <<< guild_name >>> 14 | + R = @all 15 | + 16 | repo <<< guild_name >>> 17 | 18 | -------------------------------------------------------------------------------- /template/fork_repo.patch: -------------------------------------------------------------------------------- 1 | diff -cr -N -x .git -x '*.patch' /old//conf/gitolite.conf /new//conf/gitolite.conf 2 | *** /old//conf/gitolite.conf 2016-12-23 11:00:00.000000000 -0500 3 | --- /new//conf/gitolite.conf 2016-12-23 11:00:15.859360525 -0500 4 | *************** 5 | *** 0 **** 6 | --- 1 ---- 7 | + repo <<< other_guild >>> 8 | diff -cr -N -x .git -x '*.patch' /old//ledger/transaction.ledger /new//ledger/transaction.ledger 9 | *** /old//ledger/transaction.ledger 2016-12-23 11:00:00.000000000 -0500 10 | --- /new//ledger/transaction.ledger 2016-12-23 11:00:15.859360525 -0500 11 | *************** 12 | *** 0 **** 13 | --- 1,6 ---- 14 | + <<< date >>> Fork <<< other_guild >>> 15 | + ; fork_repo 16 | + ; other_guild: <<< other_guild >>> 17 | + <<< guild_name >>>:Height:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> <<< user_height >>> XP 18 | + <<< guild_name >>>:Depth:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> -<<< user_height >>> XP 19 | + 20 | -------------------------------------------------------------------------------- /template/ledger_basics.patch: -------------------------------------------------------------------------------- 1 | diff -cr -N -x .git -x '*.patch' /old//ledger/account.ledger /new//ledger/account.ledger 2 | *** /old//ledger/account.ledger 1969-12-31 19:00:00.000000000 -0500 3 | --- /new//ledger/account.ledger 2016-12-23 20:15:11.367512488 -0500 4 | *************** 5 | *** 0 **** 6 | --- 1,28 ---- 7 | + ; Account structure is quite complex in the GitGuild, creating a symmetry between this ledger and the git tree itself. 8 | + ; A number of complex and potentially long account names may be difficult to read, but they're quite organized. 9 | + ; The basic structure is as follows. 10 | + ; 11 | + ; username:user account:repository:branch:parent commit hash:metadata 12 | + ; 13 | + ; Most of these are probably self explanatory. User account is the usual suspects of accounting: Income, Expenses, Assets, Liabilities, Equity. 14 | + ; User account also has two additional options related to voting: Height, Depth. 15 | + ; Metadata might be bitcoin or dash addresses, and/or transaction hashes. 16 | + 17 | + account <<< guild_name >>> 18 | + note The Guild's main account. If a personal guild, the owner's account. 19 | + 20 | + ; Consensus accounts, for voting. 21 | + account <<< guild_name >>>:Depth 22 | + note the Guild's voting account. XP originates here, given out by the guild to deserving members. 23 | + assert commodity == "XP" 24 | + account <<< guild_name >>>:Height 25 | + note the Guild's vote counting area. Votes by members on commits related to this guild are recorded here. 26 | + assert commodity == "XP" 27 | + 28 | + ; Normal accounting categories. Each guild/user has these. 29 | + account <<< guild_name >>>:Expenses 30 | + account <<< guild_name >>>:Equity 31 | + account <<< guild_name >>>:Income 32 | + account <<< guild_name >>>:Assets 33 | + account <<< guild_name >>>:Liabilities 34 | + 35 | diff -cr -N -x .git -x '*.patch' /old//ledger/chain.ledger /new//ledger/chain.ledger 36 | *** /old//ledger/chain.ledger 1969-12-31 19:00:00.000000000 -0500 37 | --- /new//ledger/chain.ledger 2016-12-23 20:15:53.519511733 -0500 38 | *************** 39 | *** 0 **** 40 | --- 1,7 ---- 41 | + !include commodity.ledger 42 | + !include account.ledger 43 | + !include tag.ledger 44 | + !include equity.parent 45 | + !include transaction.ledger 46 | + !include check.ledger 47 | + !include generated_check.ledger 48 | diff -cr -N -x .git -x '*.patch' /old//ledger/check.ledger /new//ledger/check.ledger 49 | *** /old//ledger/check.ledger 1969-12-31 19:00:00.000000000 -0500 50 | --- /new//ledger/check.ledger 2016-12-23 20:13:47.011513999 -0500 51 | *************** 52 | *** 0 **** 53 | --- 1,15 ---- 54 | + define GUILD_DEPTH = (-account("<<< guild_name >>>:Depth:<<< guild_name >>>").total) 55 | + define GUILD_HEIGHT = (account("<<< guild_name >>>:Height:<<< guild_name >>>").total) 56 | + 57 | + ; Each user must have net positive score 58 | + define user_vote_check(user_name) = (account(user_name + ":Height").total >= 0 XP) 59 | + 60 | + ; Each branch of this guild must have net positive score 61 | + define branch_vote_check(user_name, vote_guild_name, vote_branch) = (account(user_name + ":Height:" + vote_guild_name + ":" + vote_branch).total >= 0) 62 | + 63 | + ; Each issue must have score higher than given in the tag 64 | + define issue_vote_check(user_name, vote_guild_name, vote_branch, vote_parent, min_votes) = (account(user_name + ":Height:" + vote_guild_name + ":" + vote_branch + ":" + vote_parent).total >= GUILD_DEPTH * min_votes) 65 | + 66 | + ; user has not spent more XP than allowed on this issue 67 | + define user_issue_vote_check(user_name, vote_guild_name, vote_branch, vote_parent) = (account(user_name + ":Height").total >= abs(account(user_name + ":Depth:" + vote_guild_name + ":" + vote_branch + ":" + vote_parent).total)) 68 | + 69 | diff -cr -N -x .git -x '*.patch' /old//ledger/commodity.ledger /new//ledger/commodity.ledger 70 | *** /old//ledger/commodity.ledger 1969-12-31 19:00:00.000000000 -0500 71 | --- /new//ledger/commodity.ledger 2016-12-23 20:34:48.739491404 -0500 72 | *************** 73 | *** 0 **** 74 | --- 1,19 ---- 75 | + commodity XP 76 | + note Experience Points, used for voting on members and issues 77 | + format 1,000.00 XP 78 | + nomarket 79 | + 80 | + commodity XGG 81 | + note GitGuild token of value. Transferable and redeemable at bid rate if part of approved Income transaction. 82 | + format 1,000.0000 XGG 83 | + ; governor gitguild 84 | + 85 | + commodity DASH 86 | + note See dash.org 87 | + format 1,000.00000000 DASH 88 | + nomarket 89 | + 90 | + commodity BTC 91 | + note See bitcoin.org 92 | + format 1,000.00000000 BTC 93 | + nomarket 94 | diff -cr -N -x .git -x '*.patch' /old//ledger/equity.ledger /new//ledger/equity.ledger 95 | *** /old//ledger/equity.ledger 1969-12-31 19:00:00.000000000 -0500 96 | --- /new//ledger/equity.ledger 2016-12-23 20:14:47.879512909 -0500 97 | *************** 98 | *** 0 **** 99 | --- 1,2 ---- 100 | + # This file should always have an 'equity' summary of all history, 101 | + # including the transaction in this commit. 102 | diff -cr -N -x .git -x '*.patch' /old//ledger/equity.parent /new//ledger/equity.parent 103 | *** /old//ledger/equity.parent 1969-12-31 19:00:00.000000000 -0500 104 | --- /new//ledger/equity.parent 2016-12-23 20:14:47.879512909 -0500 105 | *************** 106 | *** 0 **** 107 | --- 1 ---- 108 | + # This file should always have an 'equity' summary of all history up to the parent. 109 | diff -cr -N -x .git -x '*.patch' /old//ledger/tag.ledger /new//ledger/tag.ledger 110 | *** /old//ledger/tag.ledger 1969-12-31 19:00:00.000000000 -0500 111 | --- /new//ledger/tag.ledger 2016-12-23 20:15:02.071512655 -0500 112 | *************** 113 | *** 0 **** 114 | --- 1,38 ---- 115 | + tag init_personal 116 | + ; patch gitguild/template/clean_gitolite_admin.patch 117 | + ; patch gitguild/template/add_member_authors.patch 118 | + ; patch gitguild/template/add_general_project_files.patch 119 | + ; patch gitguild/template/add_ledger_basics.patch 120 | + ; patch gitguild/template/personal_ledger_init.patch 121 | + ; patch gitguild/template/add_GUILD.patch 122 | + ; min_votes 0 123 | + ; endtag init_personal 124 | + 125 | + tag register_member 126 | + ; patch gitguild/template/add_member_authors.patch 127 | + ; patch gitguild/template/add_member_ledger.patch 128 | + ; patch gitguild/template/add_member_gitolite.patch 129 | + ; min_votes 0 130 | + ; endtag register_member 131 | + 132 | + tag fork_repo 133 | + ; patch gitguild/template/fork_repo.patch 134 | + ; min_votes 0.5 135 | + ; endtag fork_repo 136 | + 137 | + tag register_personal_gitguild 138 | + ; patch gitguild/template/add_member_authors.patch 139 | + ; patch gitguild/template/register_personal_gitguild_ledger.patch 140 | + ; min_votes 0.66 141 | + ; endtag register_personal_gitguild 142 | + 143 | + tag contribute 144 | + ; patch gitguild/template/contribute.patch 145 | + ; min_votes 0.66 146 | + ; endtag contribute 147 | + 148 | + tag paid_contribution 149 | + ; patch gitguild/template/paid_contribution.patch 150 | + ; min_votes 0.75 151 | + ; endtag paid_contribution 152 | + 153 | diff -cr -N -x .git -x '*.patch' /old//ledger/transaction.ledger /new//ledger/transaction.ledger 154 | *** /old//ledger/transaction.ledger 1969-12-31 19:00:00.000000000 -0500 155 | --- /new//ledger/transaction.ledger 2016-12-23 20:15:08.539512539 -0500 156 | *************** 157 | *** 0 **** 158 | --- 1 ---- 159 | + # This file should not have any transactions in the current commit. 160 | -------------------------------------------------------------------------------- /template/paid_contribution.patch: -------------------------------------------------------------------------------- 1 | diff -cr -N -x .git -x '*.patch' /old//ledger/transaction.ledger /new//ledger/transaction.ledger 2 | *** /old//ledger/transaction.ledger 2015-12-31 19:00:00.000000000 -0500 3 | --- /new//ledger/transaction.ledger 2016-12-23 20:15:53.519511733 -0500 4 | *************** 5 | *** 0 **** 6 | --- 1,12 ---- 7 | + <<< date >>> Paid Contribution 8 | + ; paid_contribution 9 | + ; wild_patch: <<< patch_path >>> 10 | + <<< user_name >>>:Income:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> -<<< XGG_amount >>> XGG 11 | + <<< user_name >>>:Assets:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> <<< XGG_amount >>> XGG 12 | + <<< guild_name >>>:Liabilities:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> -<<< XGG_amount >>> XGG 13 | + <<< guild_name >>>:Expenses:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> <<< XGG_amount >>> XGG 14 | + <<< user_name >>>:Height:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> <<< XGG_amount >>> XP 15 | + <<< user_name >>>:Depth:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> -<<< user_height >>> XP 16 | + <<< guild_name >>>:Height:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> <<< user_height >>> XP 17 | + <<< guild_name >>>:Depth:<<< guild_name >>>:<<< user_name >>>:<<< parent >>> -<<< XGG_amount >>> XP 18 | + 19 | -------------------------------------------------------------------------------- /template/personal_ledger_init.patch: -------------------------------------------------------------------------------- 1 | diff -cr -N -x .git -x '*.patch' /old//ledger/transaction.ledger /new//ledger/transaction.ledger 2 | *** /old//ledger/transaction.ledger 2016-12-23 19:04:16.631588682 -0500 3 | --- /new//ledger/transaction.ledger 2016-12-23 19:03:47.423589205 -0500 4 | *************** 5 | *** 1 **** 6 | ! # This file should not have any transactions in the current commit. 7 | --- 1,5 ---- 8 | ! 9 | ! <<< date >>> <<< user_name >>> Personal Guild Initialization 10 | ! ; init_personal 11 | ! <<< user_name >>>:Height:<<< user_name >>>:<<< user_name >>>:<<< parent >>> 1 XP 12 | ! <<< user_name >>>:Depth:<<< user_name >>>:<<< user_name >>>:<<< parent >>> -1 XP 13 | -------------------------------------------------------------------------------- /template/register_personal_gitguild_ledger.patch: -------------------------------------------------------------------------------- 1 | diff -cr -N -x .git -x './template/*.patch' /old//ledger/transaction.ledger /new//ledger/transaction.ledger 2 | *** /old//ledger/transaction.ledger 2016-12-27 17:58:48.328360708 -0500 3 | --- /new//ledger/transaction.ledger 2016-12-27 17:57:37.616361975 -0500 4 | *************** 5 | *** 1 **** 6 | --- 1,6 ---- 7 | + <<< date >>> * GitGuild Personal Registration 8 | + <<< user_name >>>:Depth:<<< user_name >>>:<<< user_name >>>:<<< parent >>> -<<< user_height >>> XP 9 | + <<< user_name >>>:Height:<<< user_name >>>:<<< user_name >>>:<<< parent >>> <<< user_height >>> XP 10 | + <<< user_name >>>:Payable:<<< user_name >>>:<<< user_name >>>:<<< parent >>> -1 XGG 11 | + gitguild:Receivable:<<< user_name >>>:<<< user_name >>>:<<< parent >>> 1 XGG 12 | 13 | --------------------------------------------------------------------------------