소스 검색

Initial Commit

Gitote 7 년 전
커밋
bc701732b4
100개의 변경된 파일4441개의 추가작업 그리고 0개의 파일을 삭제
  1. 15 0
      .dockerignore
  2. 3 0
      .gitattributes
  3. 19 0
      .gitignore
  4. 215 0
      .gitlab-ci.yml
  5. 1 0
      .gitlab/README.md
  6. 28 0
      .gitlab/issue_templates/Bug.md
  7. 12 0
      .gitlab/issue_templates/Feature.md
  8. 8 0
      .vscode/extensions.json
  9. 25 0
      .vscode/settings.json
  10. 40 0
      CONTRIBUTING.md
  11. 46 0
      Dockerfile
  12. 22 0
      LICENSE
  13. 65 0
      Makefile
  14. 1 0
      Procfile
  15. 131 0
      README.md
  16. 179 0
      cmd/admin.go
  17. 158 0
      cmd/cert.go
  18. 24 0
      cmd/cert_stub.go
  19. 38 0
      cmd/cmd.go
  20. 272 0
      cmd/hook.go
  21. 108 0
      cmd/import.go
  22. 268 0
      cmd/serv.go
  23. 754 0
      cmd/web.go
  24. 9 0
      conf/README.md
  25. 479 0
      conf/app.ini
  26. 28 0
      conf/auth.d/ldap_bind_dn.conf.example
  27. 29 0
      conf/auth.d/ldap_simple_auth.conf.example
  28. 9 0
      conf/auth.d/pam.conf.example
  29. 15 0
      conf/auth.d/smtp.conf.example
  30. 11 0
      conf/gitignore/Actionscript
  31. 5 0
      conf/gitignore/Ada
  32. 1 0
      conf/gitignore/Agda
  33. 32 0
      conf/gitignore/Android
  34. 3 0
      conf/gitignore/Anjuta
  35. 2 0
      conf/gitignore/AppEngine
  36. 3 0
      conf/gitignore/AppceleratorTitanium
  37. 13 0
      conf/gitignore/ArchLinuxPackages
  38. 27 0
      conf/gitignore/Archives
  39. 14 0
      conf/gitignore/Autotools
  40. 4 0
      conf/gitignore/BricxCC
  41. 32 0
      conf/gitignore/C
  42. 108 0
      conf/gitignore/C Sharp
  43. 28 0
      conf/gitignore/C++
  44. 12 0
      conf/gitignore/CFWheels
  45. 6 0
      conf/gitignore/CMake
  46. 6 0
      conf/gitignore/CUDA
  47. 4 0
      conf/gitignore/CVS
  48. 13 0
      conf/gitignore/CakePHP
  49. 9 0
      conf/gitignore/ChefCookbook
  50. 3 0
      conf/gitignore/Cloud9
  51. 6 0
      conf/gitignore/CodeIgniter
  52. 3 0
      conf/gitignore/CodeKit
  53. 3 0
      conf/gitignore/CommonLisp
  54. 6 0
      conf/gitignore/Composer
  55. 3 0
      conf/gitignore/Concrete5
  56. 3 0
      conf/gitignore/Coq
  57. 3 0
      conf/gitignore/CraftCMS
  58. 5 0
      conf/gitignore/DM
  59. 15 0
      conf/gitignore/Dart
  60. 2 0
      conf/gitignore/DartEditor
  61. 57 0
      conf/gitignore/Delphi
  62. 3 0
      conf/gitignore/Dreamweaver
  63. 36 0
      conf/gitignore/Drupal
  64. 4 0
      conf/gitignore/EPiServer
  65. 36 0
      conf/gitignore/Eagle
  66. 39 0
      conf/gitignore/Eclipse
  67. 2 0
      conf/gitignore/EiffelStudio
  68. 5 0
      conf/gitignore/Elisp
  69. 4 0
      conf/gitignore/Elixir
  70. 32 0
      conf/gitignore/Emacs
  71. 4 0
      conf/gitignore/Ensime
  72. 10 0
      conf/gitignore/Erlang
  73. 1 0
      conf/gitignore/Espresso
  74. 19 0
      conf/gitignore/ExpressionEngine
  75. 4 0
      conf/gitignore/ExtJs
  76. 2 0
      conf/gitignore/Fancy
  77. 13 0
      conf/gitignore/Finale
  78. 3 0
      conf/gitignore/FlexBuilder
  79. 4 0
      conf/gitignore/ForceDotCom
  80. 2 0
      conf/gitignore/FuelPHP
  81. 28 0
      conf/gitignore/GWT
  82. 5 0
      conf/gitignore/Gcov
  83. 16 0
      conf/gitignore/GitBook
  84. 24 0
      conf/gitignore/Go
  85. 8 0
      conf/gitignore/Gradle
  86. 33 0
      conf/gitignore/Grails
  87. 16 0
      conf/gitignore/Haskell
  88. 5 0
      conf/gitignore/IGORPro
  89. 2 0
      conf/gitignore/IPythonNotebook
  90. 2 0
      conf/gitignore/Idris
  91. 13 0
      conf/gitignore/JDeveloper
  92. 12 0
      conf/gitignore/Java
  93. 19 0
      conf/gitignore/Jboss
  94. 3 0
      conf/gitignore/Jekyll
  95. 46 0
      conf/gitignore/JetBrains
  96. 525 0
      conf/gitignore/Joomla
  97. 2 0
      conf/gitignore/KDevelop4
  98. 3 0
      conf/gitignore/Kate
  99. 13 0
      conf/gitignore/KiCAD
  100. 0 0
      conf/gitignore/Kohana

+ 15 - 0
.dockerignore

@@ -0,0 +1,15 @@
+packager
+packager/**
+scripts
+scripts/**
+.github/
+.github/**
+config.codekit
+.dockerignore
+*.yml
+*.md
+.bra.toml
+.editorconfig
+.gitignore
+Dockerfile*
+gitote

+ 3 - 0
.gitattributes

@@ -0,0 +1,3 @@
+conf/gitignore/* linguist-vendored
+conf/license/* linguist-vendored
+public/assets/* linguist-vendored

+ 19 - 0
.gitignore

@@ -0,0 +1,19 @@
+.DS_Store
+*.db
+custom/
+data/
+.vendor/
+.idea/
+*.iml
+public/img/avatar/
+*.exe
+.env
+*.zip
+*.exe~
+/gitote
+profile/
+*.pem
+output*
+/release
+go-bindata
+govendor

+ 215 - 0
.gitlab-ci.yml

@@ -0,0 +1,215 @@
+image: golang:alpine
+
+before_script:
+    - apk update
+    - apk --no-cache --no-progress add --virtual build-deps build-base git linux-pam-dev
+
+stages:
+    - build
+    - prepare
+    - test
+    - clean
+    - commands
+    - image-test
+    - pre-test-source
+    - deploy
+
+Build:
+    image: golang:alpine
+    stage: build
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - make build
+
+Build Dev:
+    image: golang:alpine
+    stage: build
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - make build-dev
+
+Build Dev Race:
+    image: golang:latest
+    before_script:
+        - apt-get update -qq
+        - apt-get install -y libpam-dev zip unzip
+    stage: build
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - make build-dev-race
+
+Build Prod:
+    image: golang:latest
+    before_script:
+        - apt-get update -qq
+        - apt-get install -y libpam-dev zip unzip
+    stage: build
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - wget https://gitlab.com/gitote/bindata/raw/master/go-bindata
+        - make bindata
+        - make build
+
+Docker Build:
+    image: docker:latest
+    stage: build
+    services:
+      - docker:dind
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - docker build -t gitote .
+
+Compile LESS:
+    image: golang:alpine
+    stage: prepare
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - make less
+
+Bindata:
+    image: golang:alpine
+    stage: prepare
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - wget https://gitlab.com/gitote/bindata/raw/master/go-bindata
+        - make bindata
+
+Test:
+    image: golang:latest
+    before_script:
+        - apt-get update -qq
+        - apt-get install -y libpam-dev zip unzip
+    stage: test
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - go test -v -cover -race ./...
+
+Go LOC:
+    image: golang:alpine
+    stage: test
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - go get -u github.com/hhatto/gocloc/cmd/gocloc
+        - gocloc .
+
+Clean:
+    image: golang:alpine
+    stage: clean
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - make clean
+
+Admin:
+    image: golang:alpine
+    stage: commands
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - go build
+        - ./gitote admin
+
+Hook:
+    image: golang:alpine
+    stage: commands
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - go build
+        - ./gitote hook
+
+Import:
+    image: golang:alpine
+    stage: commands
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - go build
+        - ./gitote import
+
+Cert:
+    image: golang:alpine
+    stage: commands
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - go build
+        - ./gitote cert --help
+
+Serv:
+    image: golang:alpine
+    stage: commands
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - go build
+        - ./gitote serv --help
+
+Running:
+    image: golang:alpine
+    stage: pre-test-source
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - cd gitote
+        - go build
+        - ./gitote web & sleep 20 ; kill $! || echo $?
+
+Deploy Beta:
+    image: golang:latest
+    before_script:
+        - apt-get update -qq
+        - apt-get install -y sshpass
+    stage: deploy
+    script:
+        - mkdir -p $GOPATH/src/gitote
+        - cd $GOPATH/src/gitote
+        - git clone https://gitlab.com/$CI_PROJECT_PATH.git
+        - echo "Soon"
+        - echo "Deploying to beta server"
+        - sshpass
+        - export SSHPASS=$USER_PASS 
+        #- sshpass -e scp -o stricthostkeychecking=no -r . root@142.93.212.225:go/src/gitote/gitote
+    only:
+      - master
+

+ 1 - 0
.gitlab/README.md

@@ -0,0 +1 @@
+# Issue Template

+ 28 - 0
.gitlab/issue_templates/Bug.md

@@ -0,0 +1,28 @@
+<!---
+The issue will be closed without any reasons if it does not satisfy any of the following requirements:
+
+1. Please speak English.
+2. Please do not end your title with a question mark or period.
+3. Please take a moment to search that an issue doesn't already exist.
+4. Please give all relevant information below for bug reports; incomplete details considered the invalid report.
+--->
+
+- **Gitote version** (or commit ref): 
+- **Git version**: 
+- **Operating system**: 
+- **Database** (use `[x]`):
+  - [ ] PostgreSQL
+  - [ ] MySQL
+  - [ ] MSSQL
+  - [ ] SQLite
+- **Can you reproduce the bug at** https://gitote.com:
+  - [ ] Yes (provide example URL)
+  - [ ] No
+  - [ ] Not relevant
+- **Log gist** (usually found in `log/gitote.log`):
+
+## Description
+
+...
+
+/label ~bug

+ 12 - 0
.gitlab/issue_templates/Feature.md

@@ -0,0 +1,12 @@
+---
+About: Suggest an idea for this project
+---
+
+**Describe the feature you'd like**
+A clear description of the feature you'd like implemented in Gitote.
+
+**Describe the benefits this feature would bring to Gitote users**
+Explain the measurable benefits this feature would achieve.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.

+ 8 - 0
.vscode/extensions.json

@@ -0,0 +1,8 @@
+{
+    "recommendations": [
+        "ronnidc.nunjucks",
+        "michelemelluso.code-beautifier",
+        "ms-vscode.go",
+        "robertohuertasm.vscode-icons",
+    ]
+}

+ 25 - 0
.vscode/settings.json

@@ -0,0 +1,25 @@
+{
+    "files.autoSave": "afterDelay",
+    "editor.fontSize": 14,
+    "editor.fontFamily": "'Droid Sans Mono', 'monospace', monospace, 'Droid Sans Fallback'",
+    "diffEditor.ignoreTrimWhitespace": true,
+    "editor.autoClosingBrackets": "always",
+    "editor.autoClosingQuotes": "always",
+    "editor.autoIndent": true,
+    "files.eol": "\n",
+    "search.exclude": {
+        "**/vendor/giote.com": true,
+    },
+    "html.autoClosingTags": true,
+    "html.format.enable": true,
+    "html.format.endWithNewline": true,
+    "css.colorDecorators.enable": true,
+    "less.colorDecorators.enable": true,
+    "less.lint.argumentsInColorFunction": "error",
+    "less.validate": true,
+    "terminal.explorerKind": "integrated",
+    "terminal.integrated.fontSize": 14,
+    "terminal.integrated.fontWeight": "600",
+    "merge-conflict.codeLens.enabled": true,
+    "git.autorefresh": true,
+}

+ 40 - 0
CONTRIBUTING.md

@@ -0,0 +1,40 @@
+# Contributing to Gitote
+
+> This guidelines sheet is forked from [CONTRIBUTING.md](https://github.com/drone/drone/blob/8d9c7cee56d6c2eac81dc156ce27be6716d97e68/CONTRIBUTING.md).
+
+Gitote is not perfect, and it has bugs or incomplete features in rare cases. You're welcome to tell us, or to contribute some code. This document describes details about how can you contribute to Gitote project.
+
+## Contribution guidelines
+
+Depends on the situation, you will:
+
+- Find a bug and create an issue
+- Need more functionality and make a feature request
+- Want to contribute code and open a pull request
+- Run into issue and need help
+
+### Bug Report
+
+If you find something you consider a bug, please create an issue on [GitLab](https://gitlab.com/gitote/gitote/issues). To avoid wasting time and reduce back-and-forth communication with team members, please be respect to **Issue Template**.
+
+### Feature Request
+
+There is no standard form of making a feature request. Just try to describe the feature as clearly as possible, because team members may not have experience with the functionality you're talking about.
+
+### Merge Request
+
+Please read detailed information on [Wiki](https://gitlab.com/gitote/gitote/wiki/Contributing-Code).
+
+## Code of conduct
+
+As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
+
+We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
+
+Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior can be reported by emailing yoginth@icloud.com
+
+This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)

+ 46 - 0
Dockerfile

@@ -0,0 +1,46 @@
+FROM golang:alpine AS builder
+
+MAINTAINER "Yoginth <yoginth@icloud.com>"
+
+# Install build deps
+RUN apk --no-cache --no-progress add --virtual build-deps build-base git linux-pam-dev
+WORKDIR /go/src/gitote/gitote
+COPY . .
+RUN make build TAGS="sqlite cert pam"
+
+FROM alpine:latest
+
+# Install system utils & Gitote runtime dependencies
+ADD https://github.com/tianon/gosu/releases/download/1.10/gosu-amd64 /usr/sbin/gosu
+RUN chmod +x /usr/sbin/gosu \
+  && echo http://dl-2.alpinelinux.org/alpine/edge/community/ >> /etc/apk/repositories \
+  && apk --no-cache --no-progress add \
+    bash \
+    ca-certificates \
+    curl \
+    git \
+    linux-pam \
+    openssh \
+    s6 \
+    shadow \
+    socat \
+    tzdata
+
+ENV GITOTE_CUSTOM /data/gitote
+
+# Configure LibC Name Service
+COPY docker/nsswitch.conf /etc/nsswitch.conf
+
+WORKDIR /app/gitote
+COPY docker ./docker
+COPY templates ./templates
+COPY public ./public
+COPY --from=builder /go/src/gitote/gitote .
+
+RUN ./docker/finalize.sh
+
+# Configure Docker Container
+VOLUME ["/data"]
+EXPOSE 22 3000
+ENTRYPOINT ["/app/gitote/docker/start.sh"]
+CMD ["/bin/s6-svscan", "/app/gitote/docker/s6/"]

+ 22 - 0
LICENSE

@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2015 The Gogs Authors
+Copyright (c) 2018 Gitote
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 65 - 0
Makefile

@@ -0,0 +1,65 @@
+LDFLAGS += -X "gitote/gitote/pkg/setting.BuildTime=$(shell date -u '+%Y-%m-%d %I:%M:%S %Z')"
+LDFLAGS += -X "gitote/gitote/pkg/setting.BuildGitHash=$(shell git rev-parse HEAD)"
+DATA_FILES := $(shell find conf | sed 's/ /\\ /g')
+LESS_FILES := $(wildcard public/less/gitote.less public/less/_*.less)
+GENERATED  := pkg/bindata/bindata.go public/css/gitote.css
+OS := $(shell uname)
+TAGS = ""
+BUILD_FLAGS = "-v"
+NOW = $(shell date -u '+%Y%m%d%I%M%S')
+GOVET = go tool vet -composites=false -methods=false -structtags=false
+
+.PHONY: build bindata clean
+
+.IGNORE: public/css/gitote.css
+
+all: build
+
+check: test
+
+web: build
+	./gitote web
+
+govet:
+	$(GOVET) gitote.go
+	$(GOVET) models pkg routes
+
+build: $(GENERATED)
+	go install $(BUILD_FLAGS) -ldflags '$(LDFLAGS)' -tags '$(TAGS)'
+	cp '$(GOPATH)/bin/gitote' .
+
+build-dev: $(GENERATED) govet
+	go install $(BUILD_FLAGS) -tags '$(TAGS)'
+	cp '$(GOPATH)/bin/gitote' .
+
+build-dev-race: $(GENERATED) govet
+	go install $(BUILD_FLAGS) -race -tags '$(TAGS)'
+	cp '$(GOPATH)/bin/gitote' .
+
+bindata: pkg/bindata/bindata.go
+
+pkg/bindata/bindata.go: $(DATA_FILES)
+	./go-bindata -o=$@ -ignore="\\.DS_Store|README.md|TRANSLATORS|auth.d" -pkg=bindata conf/...
+
+less: public/css/gitote.css
+
+public/css/gitote.css: $(LESS_FILES)
+	@type lessc >/dev/null 2>&1 && lessc $< >$@ || echo "lessc command not found, skipped."
+
+clean:
+	go clean -i ./...
+
+clean-mac: clean
+	find . -name ".DS_Store" -print0 | xargs -0 rm
+
+test:
+	go test -cover -race ./...
+
+alpha:
+	grep -rnw "WIP - Alpha" templates
+
+beta:
+	grep -rnw "WIP - Beta" templates
+
+todo:
+	grep -rnw "WIP - ToDo" templates

+ 1 - 0
Procfile

@@ -0,0 +1 @@
+web: cp bin/gitote . && ./gitote web -p ${PORT:=80}

+ 131 - 0
README.md

@@ -0,0 +1,131 @@
+# Gitote
+
+[![Build Status](https://gitlab.com/gitote/gitote/badges/master/pipeline.svg)](https://gitlab.com/gitote/gitote/pipelines)
+[![Docker Repository on Quay](https://quay.io/repository/gitote/gitote/status "Docker Repository on Quay")](https://quay.io/repository/gitote/gitote)
+[![Go Report](https://goreportcard.com/badge/gitlab.com/gitote/gitote)](https://goreportcard.com/report/gitlab.com/gitote/gitote)
+[![Bountysource](https://img.shields.io/bountysource/team/gitote/activity.svg)](https://www.bountysource.com/teams/gitote)
+[![Website Status](https://img.shields.io/website-up-down-green-red/http/gitote.ml.svg?label=status)](https://gitote.ml)
+
+#### Software version control made simple!
+
+Welcome to the [gitote](https://gitote.com) codebase. We are so excited to have you. With your help, we can build out Gitote to be more stable and better serve our platform.
+
+## What is gitote?
+
+[Gitote](https://gitote.com) is an open source end-to-end software development platform with built-in version control, issue tracking, code review, and more.
+
+## Contributing
+
+We expect contributors to abide by our underlying [code of conduct](CONDUCT.md). All conversations and discussions on GitLab (issues, merge requests) and across Gitote must be respectful and harassment-free.
+
+### Where to contribute
+
+When in doubt, ask a [core team member](#core-team)! You can mention us in any issues . Any issue with ~7579403 tag is typically a good place to start.
+
+**Refactoring** code, e.g. improving the code without modifying the behavior is an area that can probably be done based on intuition and may not require much communication to be merged.
+
+**Fixing bugs** may also not require a lot of communication, but the more the better. Please surround bug fixes with ample tests. Bugs are magnets for other bugs. Write tests near bugs!
+
+**Building features** is the area which will require the most communication and/or negotiation. Every feature is subjective and open for debate. The [product roadmap](https://gitlab.com/gitote/gitote/boards/716462) should be a good guide to follow. As always, when in doubt, ask!
+
+### How to contribute
+
+1.  Fork the project & clone locally. Follow the initial setup [here](#getting-started).
+2.  Create a branch, naming it either a feature or bug: `git checkout -b feature/that-new-feature` or `bug/fixing-that-bug`
+3.  Code and commit your changes. Bonus points if you write a [good commit message](https://chris.beams.io/posts/git-commit/): `git commit -m 'Add some feature'`
+4.  Push to the branch: `git push origin feature/that-new-feature`
+5.  [Create a merge request](#create-a-merge-request) for your branch 🎉
+
+## Contribution guideline
+
+### Create an issue
+
+Nobody's perfect. Something doesn't work? Or could be done better? Let us know by creating an issue.
+
+PS: a clear and detailed issue gets lots of love, all you have to do is follow the issue template!
+
+#### Clean code with tests
+
+Some existing code may be poorly written or untested, so we must have more scrutiny going forward. We test with **go test**, let us know if you have any questions about this!
+
+#### Create a megre request
+
+* Try to keep the megre requests small. A megre request should try its very best to address only a single concern.
+* Make sure all tests pass and add additional tests for the code you submit.
+* Document your reasoning behind the changes. Explain why you wrote the code in the way you did. The code should explain what it does.
+* If there's an existing issue related to the megre request, reference to it by adding something like `References/Closes/Fixes/Resolves #305`, where 305 is the issue number. [More info here](https://docs.gitlab.com/ee/user/project/issues/closing_issues.html#via-merge-request)
+* If you follow the megre request template, you can't go wrong.
+
+## Codebase
+
+### The stack
+
+We run on a **Go** backend.
+
+Additional technologies and services are listed on [our stackshare](https://stackshare.com/gitote).
+
+## Features
+
+- Activity timeline
+- **SSH** and **HTTP/HTTPS** protocols
+- Account/Organization/Repository management
+- Add/Remove repository collaborators
+- Repository/Organization **webhooks** (including Slack and Discord)
+- Repository **Git hooks/deploy keys**
+- Repository **issues**, **pull requests**, **wiki** and **protected branches**
+- **Migrate** and **mirror** repository and its wiki
+- **Web editor** for repository files and wiki
+- **Jupyter Notebook**
+- **Two-factor authentication**
+- **Gravatar** and **Federated avatar** with custom source
+- **Mail** service
+
+## Product Roadmap
+
+Our new product roadmap can be found [here](https://gitlab.com/gitote/gitote/boards/716462). Many notes need to be converted to issues but this should provide an overview of features we plan to work on, as well as features we are considering.
+
+Core team members will move issues along the project board as they progress.
+
+* Backlog: an accumulation of uncompleted work or matters needing to be dealt with.
+* Bug: bugs to be fixed.
+* Feature Requests: features up for discussion.
+* Closed: features we're committed to building -- free for contributors to work on, but please communicate with the owner beforehand.
+
+## Core team
+
+<table>
+  <tr>
+    <td>
+      <a href="https://twitter.com/yogicodes">
+        <img src="https://s.gravatar.com/avatar/18d22b6c2ffd6547a095cd734770fb44?s=100">
+      </a>
+      <h4 align="center"><a href="https://twitter.com/yogicodes">Yoginth</a></h4>
+    </td>
+    <td>
+      <a href="https://twitter.com/GitoteHQ">
+        <img src="https://s.gravatar.com/avatar/894559413cde06d4aacc1a05bd7f3205?s=100">
+      </a>
+      <h4 align="center"><a href="https://twitter.com/GitoteHQ">OteBot</a></h4>
+    </td>
+  </tr>
+</table>
+
+## Sponsors
+
+<p>
+  <a href="https://browserstack.com" target="_blank">
+    <img height="50px" src="https://cdn.jsdelivr.net/npm/gitote@1.1.1/img/sponsors/browserstack.png">
+  </a>
+</p>
+<br/>
+<p>
+  <a href="https://www.digitalocean.com?utm_medium=opensource&utm_source=Gitote">
+    <img height="50px" src="https://cdn.jsdelivr.net/npm/gitote@1.1.3/img/sponsors/digitalocean.svg">
+  </a>
+</p>
+
+## License
+
+This program is free software: you can redistribute it and/or modify it under the terms of the **MIT License**. Please see the [LICENSE](https://gitlab.com/gitote/gitote/blob/master/LICENSE) file in our repository for the full text.
+
+###### Happy Coding ❤️

+ 179 - 0
cmd/admin.go

@@ -0,0 +1,179 @@
+package cmd
+
+import (
+	"fmt"
+	"gitote/gitote/models"
+	"gitote/gitote/pkg/setting"
+	"reflect"
+	"runtime"
+
+	"github.com/urfave/cli"
+)
+
+var (
+	Admin = cli.Command{
+		Name:        "admin",
+		Usage:       "Perform admin operations on command line",
+		Description: "Perform admin operations on command line",
+		Subcommands: []cli.Command{
+			subcmdCreateUser,
+			subcmdDeleteInactivateUsers,
+			subcmdDeleteRepositoryArchives,
+			subcmdDeleteMissingRepositories,
+			subcmdGitGcRepos,
+			subcmdRewriteAuthorizedKeys,
+			subcmdSyncRepositoryHooks,
+			subcmdReinitMissingRepositories,
+		},
+	}
+
+	subcmdCreateUser = cli.Command{
+		Name:   "create-user",
+		Usage:  "Create a new user in database",
+		Action: runCreateUser,
+		Flags: []cli.Flag{
+			stringFlag("name", "", "Username"),
+			stringFlag("password", "", "User password"),
+			stringFlag("email", "", "User email address"),
+			boolFlag("admin", "User is an admin"),
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+	}
+
+	subcmdDeleteInactivateUsers = cli.Command{
+		Name:  "delete-inactive-users",
+		Usage: "Delete all inactive accounts",
+		Action: adminDashboardOperation(
+			models.DeleteInactivateUsers,
+			"All inactivate accounts have been deleted successfully",
+		),
+		Flags: []cli.Flag{
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+	}
+
+	subcmdDeleteRepositoryArchives = cli.Command{
+		Name:  "delete-repository-archives",
+		Usage: "Delete all repositories archives",
+		Action: adminDashboardOperation(
+			models.DeleteRepositoryArchives,
+			"All repositories archives have been deleted successfully",
+		),
+		Flags: []cli.Flag{
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+	}
+
+	subcmdDeleteMissingRepositories = cli.Command{
+		Name:  "delete-missing-repositories",
+		Usage: "Delete all repository records that lost Git files",
+		Action: adminDashboardOperation(
+			models.DeleteMissingRepositories,
+			"All repositories archives have been deleted successfully",
+		),
+		Flags: []cli.Flag{
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+	}
+
+	subcmdGitGcRepos = cli.Command{
+		Name:  "collect-garbage",
+		Usage: "Do garbage collection on repositories",
+		Action: adminDashboardOperation(
+			models.GitGcRepos,
+			"All repositories have done garbage collection successfully",
+		),
+		Flags: []cli.Flag{
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+	}
+
+	subcmdRewriteAuthorizedKeys = cli.Command{
+		Name:  "rewrite-authorized-keys",
+		Usage: "Rewrite '.ssh/authorized_keys' file (caution: non-Gitote keys will be lost)",
+		Action: adminDashboardOperation(
+			models.RewriteAuthorizedKeys,
+			"All public keys have been rewritten successfully",
+		),
+		Flags: []cli.Flag{
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+	}
+
+	subcmdSyncRepositoryHooks = cli.Command{
+		Name:  "resync-hooks",
+		Usage: "Resync pre-receive, update and post-receive hooks",
+		Action: adminDashboardOperation(
+			models.SyncRepositoryHooks,
+			"All repositories' pre-receive, update and post-receive hooks have been resynced successfully",
+		),
+		Flags: []cli.Flag{
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+	}
+
+	subcmdReinitMissingRepositories = cli.Command{
+		Name:  "reinit-missing-repositories",
+		Usage: "Reinitialize all repository records that lost Git files",
+		Action: adminDashboardOperation(
+			models.ReinitMissingRepositories,
+			"All repository records that lost Git files have been reinitialized successfully",
+		),
+		Flags: []cli.Flag{
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+	}
+)
+
+func runCreateUser(c *cli.Context) error {
+	if !c.IsSet("name") {
+		return fmt.Errorf("Username is not specified")
+	} else if !c.IsSet("password") {
+		return fmt.Errorf("Password is not specified")
+	} else if !c.IsSet("email") {
+		return fmt.Errorf("Email is not specified")
+	}
+
+	if c.IsSet("config") {
+		setting.CustomConf = c.String("config")
+	}
+
+	setting.NewContext()
+	models.LoadConfigs()
+	models.SetEngine()
+
+	if err := models.CreateUser(&models.User{
+		Name:         c.String("name"),
+		Email:        c.String("email"),
+		Passwd:       c.String("password"),
+		ThemeColor:   "#161616",
+		IsActive:     true,
+		ShowSponsors: true,
+		IsAdmin:      c.Bool("admin"),
+	}); err != nil {
+		return fmt.Errorf("CreateUser: %v", err)
+	}
+
+	fmt.Printf("New user '%s' has been successfully created!\n", c.String("name"))
+	return nil
+}
+
+func adminDashboardOperation(operation func() error, successMessage string) func(*cli.Context) error {
+	return func(c *cli.Context) error {
+		if c.IsSet("config") {
+			setting.CustomConf = c.String("config")
+		}
+
+		setting.NewContext()
+		models.LoadConfigs()
+		models.SetEngine()
+
+		if err := operation(); err != nil {
+			functionName := runtime.FuncForPC(reflect.ValueOf(operation).Pointer()).Name()
+			return fmt.Errorf("%s: %v", functionName, err)
+		}
+
+		fmt.Printf("%s\n", successMessage)
+		return nil
+	}
+}

+ 158 - 0
cmd/cert.go

@@ -0,0 +1,158 @@
+// +build cert
+
+package cmd
+
+import (
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"log"
+	"math/big"
+	"net"
+	"os"
+	"strings"
+	"time"
+
+	"github.com/urfave/cli"
+)
+
+var Cert = cli.Command{
+	Name:  "cert",
+	Usage: "Generate self-signed certificate",
+	Description: `Generate a self-signed X.509 certificate for a TLS server.
+Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
+	Action: runCert,
+	Flags: []cli.Flag{
+		stringFlag("host", "", "Comma-separated hostnames and IPs to generate a certificate for"),
+		stringFlag("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521"),
+		intFlag("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set"),
+		stringFlag("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011"),
+		durationFlag("duration", 365*24*time.Hour, "Duration that certificate is valid for"),
+		boolFlag("ca", "whether this cert should be its own Certificate Authority"),
+	},
+}
+
+func publicKey(priv interface{}) interface{} {
+	switch k := priv.(type) {
+	case *rsa.PrivateKey:
+		return &k.PublicKey
+	case *ecdsa.PrivateKey:
+		return &k.PublicKey
+	default:
+		return nil
+	}
+}
+
+func pemBlockForKey(priv interface{}) *pem.Block {
+	switch k := priv.(type) {
+	case *rsa.PrivateKey:
+		return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
+	case *ecdsa.PrivateKey:
+		b, err := x509.MarshalECPrivateKey(k)
+		if err != nil {
+			log.Fatalf("Unable to marshal ECDSA private key: %v\n", err)
+		}
+		return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
+	default:
+		return nil
+	}
+}
+
+func runCert(ctx *cli.Context) error {
+	if len(ctx.String("host")) == 0 {
+		log.Fatal("Missing required --host parameter")
+	}
+
+	var priv interface{}
+	var err error
+	switch ctx.String("ecdsa-curve") {
+	case "":
+		priv, err = rsa.GenerateKey(rand.Reader, ctx.Int("rsa-bits"))
+	case "P224":
+		priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
+	case "P256":
+		priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	case "P384":
+		priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
+	case "P521":
+		priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
+	default:
+		log.Fatalf("Unrecognized elliptic curve: %q", ctx.String("ecdsa-curve"))
+	}
+	if err != nil {
+		log.Fatalf("Failed to generate private key: %s", err)
+	}
+
+	var notBefore time.Time
+	if len(ctx.String("start-date")) == 0 {
+		notBefore = time.Now()
+	} else {
+		notBefore, err = time.Parse("Jan 2 15:04:05 2006", ctx.String("start-date"))
+		if err != nil {
+			log.Fatalf("Failed to parse creation date: %s", err)
+		}
+	}
+
+	notAfter := notBefore.Add(ctx.Duration("duration"))
+
+	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+	if err != nil {
+		log.Fatalf("Failed to generate serial number: %s", err)
+	}
+
+	template := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Acme Co"},
+			CommonName:   "Gitote",
+		},
+		NotBefore: notBefore,
+		NotAfter:  notAfter,
+
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+		BasicConstraintsValid: true,
+	}
+
+	hosts := strings.Split(ctx.String("host"), ",")
+	for _, h := range hosts {
+		if ip := net.ParseIP(h); ip != nil {
+			template.IPAddresses = append(template.IPAddresses, ip)
+		} else {
+			template.DNSNames = append(template.DNSNames, h)
+		}
+	}
+
+	if ctx.Bool("ca") {
+		template.IsCA = true
+		template.KeyUsage |= x509.KeyUsageCertSign
+	}
+
+	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
+	if err != nil {
+		log.Fatalf("Failed to create certificate: %s", err)
+	}
+
+	certOut, err := os.Create("cert.pem")
+	if err != nil {
+		log.Fatalf("Failed to open cert.pem for writing: %s", err)
+	}
+	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
+	certOut.Close()
+	log.Println("Written cert.pem")
+
+	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		log.Fatalf("Failed to open key.pem for writing: %v\n", err)
+	}
+	pem.Encode(keyOut, pemBlockForKey(priv))
+	keyOut.Close()
+	log.Println("Written key.pem")
+
+	return nil
+}

+ 24 - 0
cmd/cert_stub.go

@@ -0,0 +1,24 @@
+// +build !cert
+
+package cmd
+
+import (
+	"fmt"
+	"os"
+
+	"github.com/urfave/cli"
+)
+
+var Cert = cli.Command{
+	Name:        "cert",
+	Usage:       "Generate self-signed certificate",
+	Description: `Please use build tags "cert" to rebuild Gitote in order to have this ability`,
+	Action:      runCert,
+}
+
+func runCert(ctx *cli.Context) error {
+	fmt.Println("Command cert not available, please use build tags 'cert' to rebuild.")
+	os.Exit(1)
+
+	return nil
+}

+ 38 - 0
cmd/cmd.go

@@ -0,0 +1,38 @@
+package cmd
+
+import (
+	"time"
+
+	"github.com/urfave/cli"
+)
+
+func stringFlag(name, value, usage string) cli.StringFlag {
+	return cli.StringFlag{
+		Name:  name,
+		Value: value,
+		Usage: usage,
+	}
+}
+
+func boolFlag(name, usage string) cli.BoolFlag {
+	return cli.BoolFlag{
+		Name:  name,
+		Usage: usage,
+	}
+}
+
+func intFlag(name string, value int, usage string) cli.IntFlag {
+	return cli.IntFlag{
+		Name:  name,
+		Value: value,
+		Usage: usage,
+	}
+}
+
+func durationFlag(name string, value time.Duration, usage string) cli.DurationFlag {
+	return cli.DurationFlag{
+		Name:  name,
+		Value: value,
+		Usage: usage,
+	}
+}

+ 272 - 0
cmd/hook.go

@@ -0,0 +1,272 @@
+package cmd
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"gitote/gitote/models"
+	"gitote/gitote/models/errors"
+	"gitote/gitote/pkg/httplib"
+	"gitote/gitote/pkg/mailer"
+	"gitote/gitote/pkg/setting"
+	"gitote/gitote/pkg/template"
+	http "gitote/gitote/routes/repo"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"strings"
+
+	"github.com/Unknwon/com"
+	"github.com/urfave/cli"
+	"gitlab.com/gitote/git-module"
+	log "gopkg.in/clog.v1"
+)
+
+var (
+	Hook = cli.Command{
+		Name:        "hook",
+		Usage:       "Delegate commands to corresponding Git hooks",
+		Description: "All sub-commands should only be called by Git",
+		Flags: []cli.Flag{
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+		Subcommands: []cli.Command{
+			subcmdHookPreReceive,
+			subcmdHookUpadte,
+			subcmdHookPostReceive,
+		},
+	}
+
+	subcmdHookPreReceive = cli.Command{
+		Name:        "pre-receive",
+		Usage:       "Delegate pre-receive Git hook",
+		Description: "This command should only be called by Git",
+		Action:      runHookPreReceive,
+	}
+	subcmdHookUpadte = cli.Command{
+		Name:        "update",
+		Usage:       "Delegate update Git hook",
+		Description: "This command should only be called by Git",
+		Action:      runHookUpdate,
+	}
+	subcmdHookPostReceive = cli.Command{
+		Name:        "post-receive",
+		Usage:       "Delegate post-receive Git hook",
+		Description: "This command should only be called by Git",
+		Action:      runHookPostReceive,
+	}
+)
+
+func runHookPreReceive(c *cli.Context) error {
+	if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
+		return nil
+	}
+	setup(c, "hooks/pre-receive.log", true)
+
+	isWiki := strings.Contains(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
+
+	buf := bytes.NewBuffer(nil)
+	scanner := bufio.NewScanner(os.Stdin)
+	for scanner.Scan() {
+		buf.Write(scanner.Bytes())
+		buf.WriteByte('\n')
+
+		if isWiki {
+			continue
+		}
+
+		fields := bytes.Fields(scanner.Bytes())
+		if len(fields) != 3 {
+			continue
+		}
+		oldCommitID := string(fields[0])
+		newCommitID := string(fields[1])
+		branchName := strings.TrimPrefix(string(fields[2]), git.BRANCH_PREFIX)
+
+		// Branch protection
+		repoID := com.StrTo(os.Getenv(http.ENV_REPO_ID)).MustInt64()
+		protectBranch, err := models.GetProtectBranchOfRepoByName(repoID, branchName)
+		if err != nil {
+			if errors.IsErrBranchNotExist(err) {
+				continue
+			}
+			fail("Internal error", "GetProtectBranchOfRepoByName [repo_id: %d, branch: %s]: %v", repoID, branchName, err)
+		}
+		if !protectBranch.Protected {
+			continue
+		}
+
+		// Whitelist users can bypass require pull request check
+		bypassRequirePullRequest := false
+
+		// Check if user is in whitelist when enabled
+		userID := com.StrTo(os.Getenv(http.ENV_AUTH_USER_ID)).MustInt64()
+		if protectBranch.EnableWhitelist {
+			if !models.IsUserInProtectBranchWhitelist(repoID, userID, branchName) {
+				fail(fmt.Sprintf("Branch '%s' is protected and you are not in the push whitelist", branchName), "")
+			}
+
+			bypassRequirePullRequest = true
+		}
+
+		// Check if branch allows direct push
+		if !bypassRequirePullRequest && protectBranch.RequirePullRequest {
+			fail(fmt.Sprintf("Branch '%s' is protected and commits must be merged through pull request", branchName), "")
+		}
+
+		// check and deletion
+		if newCommitID == git.EMPTY_SHA {
+			fail(fmt.Sprintf("Branch '%s' is protected from deletion", branchName), "")
+		}
+
+		// Check force push
+		output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).
+			RunInDir(models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME)))
+		if err != nil {
+			fail("Internal error", "Fail to detect force push: %v", err)
+		} else if len(output) > 0 {
+			fail(fmt.Sprintf("Branch '%s' is protected from force push", branchName), "")
+		}
+	}
+
+	customHooksPath := filepath.Join(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), "pre-receive")
+	if !com.IsFile(customHooksPath) {
+		return nil
+	}
+
+	var hookCmd *exec.Cmd
+	if setting.IsWindows {
+		hookCmd = exec.Command("bash.exe", "custom_hooks/pre-receive")
+	} else {
+		hookCmd = exec.Command(customHooksPath)
+	}
+	hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))
+	hookCmd.Stdout = os.Stdout
+	hookCmd.Stdin = buf
+	hookCmd.Stderr = os.Stderr
+	if err := hookCmd.Run(); err != nil {
+		fail("Internal error", "Fail to execute custom pre-receive hook: %v", err)
+	}
+	return nil
+}
+
+func runHookUpdate(c *cli.Context) error {
+	if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
+		return nil
+	}
+	setup(c, "hooks/update.log", false)
+
+	args := c.Args()
+	if len(args) != 3 {
+		fail("Arguments received are not equal to three", "Arguments received are not equal to three")
+	} else if len(args[0]) == 0 {
+		fail("First argument 'refName' is empty", "First argument 'refName' is empty")
+	}
+
+	customHooksPath := filepath.Join(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), "update")
+	if !com.IsFile(customHooksPath) {
+		return nil
+	}
+
+	var hookCmd *exec.Cmd
+	if setting.IsWindows {
+		hookCmd = exec.Command("bash.exe", append([]string{"custom_hooks/update"}, args...)...)
+	} else {
+		hookCmd = exec.Command(customHooksPath, args...)
+	}
+	hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))
+	hookCmd.Stdout = os.Stdout
+	hookCmd.Stdin = os.Stdin
+	hookCmd.Stderr = os.Stderr
+	if err := hookCmd.Run(); err != nil {
+		fail("Internal error", "Fail to execute custom pre-receive hook: %v", err)
+	}
+	return nil
+}
+
+func runHookPostReceive(c *cli.Context) error {
+	if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
+		return nil
+	}
+	setup(c, "hooks/post-receive.log", true)
+
+	// Post-receive hook does more than just gather Git information,
+	// so we need to setup additional services for email notifications.
+	setting.NewPostReceiveHookServices()
+	mailer.NewContext()
+	mailer.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"),
+		path.Join(setting.CustomPath, "templates/mail"), template.NewFuncMap())
+
+	isWiki := strings.Contains(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
+
+	buf := bytes.NewBuffer(nil)
+	scanner := bufio.NewScanner(os.Stdin)
+	for scanner.Scan() {
+		buf.Write(scanner.Bytes())
+		buf.WriteByte('\n')
+
+		// TODO: support news feeds for wiki
+		if isWiki {
+			continue
+		}
+
+		fields := bytes.Fields(scanner.Bytes())
+		if len(fields) != 3 {
+			continue
+		}
+
+		options := models.PushUpdateOptions{
+			OldCommitID:  string(fields[0]),
+			NewCommitID:  string(fields[1]),
+			RefFullName:  string(fields[2]),
+			PusherID:     com.StrTo(os.Getenv(http.ENV_AUTH_USER_ID)).MustInt64(),
+			PusherName:   os.Getenv(http.ENV_AUTH_USER_NAME),
+			RepoUserName: os.Getenv(http.ENV_REPO_OWNER_NAME),
+			RepoName:     os.Getenv(http.ENV_REPO_NAME),
+		}
+		if err := models.PushUpdate(options); err != nil {
+			log.Error(2, "PushUpdate: %v", err)
+		}
+
+		// Ask for running deliver hook and test pull request tasks
+		reqURL := setting.LocalURL + options.RepoUserName + "/" + options.RepoName + "/tasks/trigger?branch=" +
+			template.EscapePound(strings.TrimPrefix(options.RefFullName, git.BRANCH_PREFIX)) +
+			"&secret=" + os.Getenv(http.ENV_REPO_OWNER_SALT_MD5) +
+			"&pusher=" + os.Getenv(http.ENV_AUTH_USER_ID)
+		log.Trace("Trigger task: %s", reqURL)
+
+		resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{
+			InsecureSkipVerify: true,
+		}).Response()
+		if err == nil {
+			resp.Body.Close()
+			if resp.StatusCode/100 != 2 {
+				log.Error(2, "Fail to trigger task: not 2xx response code")
+			}
+		} else {
+			log.Error(2, "Fail to trigger task: %v", err)
+		}
+	}
+
+	customHooksPath := filepath.Join(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), "post-receive")
+	if !com.IsFile(customHooksPath) {
+		return nil
+	}
+
+	var hookCmd *exec.Cmd
+	if setting.IsWindows {
+		hookCmd = exec.Command("bash.exe", "custom_hooks/post-receive")
+	} else {
+		hookCmd = exec.Command(customHooksPath)
+	}
+	hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))
+	hookCmd.Stdout = os.Stdout
+	hookCmd.Stdin = buf
+	hookCmd.Stderr = os.Stderr
+	if err := hookCmd.Run(); err != nil {
+		fail("Internal error", "Fail to execute custom post-receive hook: %v", err)
+	}
+	return nil
+}

+ 108 - 0
cmd/import.go

@@ -0,0 +1,108 @@
+package cmd
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"gitote/gitote/pkg/setting"
+	"os"
+	"path/filepath"
+	"time"
+
+	"github.com/Unknwon/com"
+	"github.com/urfave/cli"
+)
+
+var (
+	Import = cli.Command{
+		Name:  "import",
+		Usage: "Import portable data as local Gitote data",
+		Description: `Allow user import data from other Gitote installations to local instance
+without manually hacking the data files`,
+		Subcommands: []cli.Command{
+			subcmdImportLocale,
+		},
+	}
+
+	subcmdImportLocale = cli.Command{
+		Name:   "locale",
+		Usage:  "Import locale files to local repository",
+		Action: runImportLocale,
+		Flags: []cli.Flag{
+			stringFlag("source", "", "Source directory that stores new locale files"),
+			stringFlag("target", "", "Target directory that stores old locale files"),
+			stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+		},
+	}
+)
+
+func runImportLocale(c *cli.Context) error {
+	if !c.IsSet("source") {
+		return fmt.Errorf("Source directory is not specified")
+	} else if !c.IsSet("target") {
+		return fmt.Errorf("Target directory is not specified")
+	}
+	if !com.IsDir(c.String("source")) {
+		return fmt.Errorf("Source directory does not exist or is not a directory")
+	} else if !com.IsDir(c.String("target")) {
+		return fmt.Errorf("Target directory does not exist or is not a directory")
+	}
+
+	if c.IsSet("config") {
+		setting.CustomConf = c.String("config")
+	}
+
+	setting.NewContext()
+
+	now := time.Now()
+
+	line := make([]byte, 0, 100)
+	badChars := []byte(`="`)
+	escapedQuotes := []byte(`\"`)
+	regularQuotes := []byte(`"`)
+	// Cut out en-US.
+	for _, lang := range setting.Langs[1:] {
+		name := fmt.Sprintf("locale_%s.ini", lang)
+		source := filepath.Join(c.String("source"), name)
+		target := filepath.Join(c.String("target"), name)
+		if !com.IsFile(source) {
+			continue
+		}
+
+		// Crowdin surrounds double quotes for strings contain quotes inside,
+		// this breaks INI parser, we need to fix that.
+		sr, err := os.Open(source)
+		if err != nil {
+			return fmt.Errorf("Open: %v", err)
+		}
+
+		tw, err := os.Create(target)
+		if err != nil {
+			if err != nil {
+				return fmt.Errorf("Open: %v", err)
+			}
+		}
+
+		scanner := bufio.NewScanner(sr)
+		for scanner.Scan() {
+			line = scanner.Bytes()
+			idx := bytes.Index(line, badChars)
+			if idx > -1 && line[len(line)-1] == '"' {
+				// We still want the "=" sign
+				line = append(line[:idx+1], line[idx+2:len(line)-1]...)
+				line = bytes.Replace(line, escapedQuotes, regularQuotes, -1)
+			}
+			tw.Write(line)
+			tw.WriteString("\n")
+		}
+		sr.Close()
+		tw.Close()
+
+		// Modification time of files from Crowdin often ahead of current,
+		// so we need to set back to current.
+		os.Chtimes(target, now, now)
+	}
+
+	fmt.Println("Locale files has been successfully imported!")
+	return nil
+}

+ 268 - 0
cmd/serv.go

@@ -0,0 +1,268 @@
+package cmd
+
+import (
+	"fmt"
+	"gitote/gitote/models"
+	"gitote/gitote/models/errors"
+	"gitote/gitote/pkg/setting"
+	http "gitote/gitote/routes/repo"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"github.com/Unknwon/com"
+	"github.com/urfave/cli"
+	log "gopkg.in/clog.v1"
+)
+
+const (
+	_ACCESS_DENIED_MESSAGE = "Repository does not exist or you do not have access"
+)
+
+var Serv = cli.Command{
+	Name:        "serv",
+	Usage:       "This command should only be called by SSH shell",
+	Description: `Serv provide access auth for repositories`,
+	Action:      runServ,
+	Flags: []cli.Flag{
+		stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+	},
+}
+
+func fail(userMessage, logMessage string, args ...interface{}) {
+	fmt.Fprintln(os.Stderr, "Gitote:", userMessage)
+
+	if len(logMessage) > 0 {
+		if !setting.ProdMode {
+			fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
+		}
+		log.Fatal(3, logMessage, args...)
+	}
+
+	os.Exit(1)
+}
+
+func setup(c *cli.Context, logPath string, connectDB bool) {
+	if c.IsSet("config") {
+		setting.CustomConf = c.String("config")
+	} else if c.GlobalIsSet("config") {
+		setting.CustomConf = c.GlobalString("config")
+	}
+
+	setting.NewContext()
+
+	level := log.TRACE
+	if setting.ProdMode {
+		level = log.ERROR
+	}
+	log.New(log.FILE, log.FileConfig{
+		Level:    level,
+		Filename: filepath.Join(setting.LogRootPath, logPath),
+		FileRotationConfig: log.FileRotationConfig{
+			Rotate:  true,
+			Daily:   true,
+			MaxDays: 3,
+		},
+	})
+	log.Delete(log.CONSOLE) // Remove primary logger
+
+	if !connectDB {
+		return
+	}
+
+	models.LoadConfigs()
+
+	if setting.UseSQLite3 {
+		workDir, _ := setting.WorkDir()
+		os.Chdir(workDir)
+	}
+
+	if err := models.SetEngine(); err != nil {
+		fail("Internal error", "SetEngine: %v", err)
+	}
+}
+
+func parseSSHCmd(cmd string) (string, string) {
+	ss := strings.SplitN(cmd, " ", 2)
+	if len(ss) != 2 {
+		return "", ""
+	}
+	return ss[0], strings.Replace(ss[1], "'/", "'", 1)
+}
+
+func checkDeployKey(key *models.PublicKey, repo *models.Repository) {
+	// Check if this deploy key belongs to current repository.
+	if !models.HasDeployKey(key.ID, repo.ID) {
+		fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
+	}
+
+	// Update deploy key activity.
+	deployKey, err := models.GetDeployKeyByRepo(key.ID, repo.ID)
+	if err != nil {
+		fail("Internal error", "GetDeployKey: %v", err)
+	}
+
+	deployKey.Updated = time.Now()
+	if err = models.UpdateDeployKey(deployKey); err != nil {
+		fail("Internal error", "UpdateDeployKey: %v", err)
+	}
+}
+
+var (
+	allowedCommands = map[string]models.AccessMode{
+		"git-upload-pack":    models.ACCESS_MODE_READ,
+		"git-upload-archive": models.ACCESS_MODE_READ,
+		"git-receive-pack":   models.ACCESS_MODE_WRITE,
+	}
+)
+
+func runServ(c *cli.Context) error {
+	setup(c, "serv.log", true)
+
+	if setting.SSH.Disabled {
+		println("Gitote: SSH has been disabled")
+		return nil
+	}
+
+	if len(c.Args()) < 1 {
+		fail("Not enough arguments", "Not enough arguments")
+	}
+
+	sshCmd := os.Getenv("SSH_ORIGINAL_COMMAND")
+	if len(sshCmd) == 0 {
+		println("Hi there, You've successfully authenticated, but Gitote does not provide shell access.")
+		println("If this is unexpected, please log in with password and setup Gitote under another user.")
+		return nil
+	}
+
+	verb, args := parseSSHCmd(sshCmd)
+	repoFullName := strings.ToLower(strings.Trim(args, "'"))
+	repoFields := strings.SplitN(repoFullName, "/", 2)
+	if len(repoFields) != 2 {
+		fail("Invalid repository path", "Invalid repository path: %v", args)
+	}
+	ownerName := strings.ToLower(repoFields[0])
+	repoName := strings.TrimSuffix(strings.ToLower(repoFields[1]), ".git")
+	repoName = strings.TrimSuffix(repoName, ".wiki")
+
+	owner, err := models.GetUserByName(ownerName)
+	if err != nil {
+		if errors.IsUserNotExist(err) {
+			fail("Repository owner does not exist", "Unregistered owner: %s", ownerName)
+		}
+		fail("Internal error", "Fail to get repository owner '%s': %v", ownerName, err)
+	}
+
+	repo, err := models.GetRepositoryByName(owner.ID, repoName)
+	if err != nil {
+		if errors.IsRepoNotExist(err) {
+			fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", owner.Name, repoName)
+		}
+		fail("Internal error", "Fail to get repository: %v", err)
+	}
+	repo.Owner = owner
+
+	requestMode, ok := allowedCommands[verb]
+	if !ok {
+		fail("Unknown git command", "Unknown git command '%s'", verb)
+	}
+
+	// Prohibit push to mirror repositories.
+	if requestMode > models.ACCESS_MODE_READ && repo.IsMirror {
+		fail("Mirror repository is read-only", "")
+	}
+
+	// Allow anonymous (user is nil) clone for public repositories.
+	var user *models.User
+
+	key, err := models.GetPublicKeyByID(com.StrTo(strings.TrimPrefix(c.Args()[0], "key-")).MustInt64())
+	if err != nil {
+		fail("Invalid key ID", "Invalid key ID '%s': %v", c.Args()[0], err)
+	}
+
+	if requestMode == models.ACCESS_MODE_WRITE || repo.IsPrivate {
+		// Check deploy key or user key.
+		if key.IsDeployKey() {
+			if key.Mode < requestMode {
+				fail("Key permission denied", "Cannot push with deployment key: %d", key.ID)
+			}
+			checkDeployKey(key, repo)
+		} else {
+			user, err = models.GetUserByKeyID(key.ID)
+			if err != nil {
+				fail("Internal error", "Fail to get user by key ID '%d': %v", key.ID, err)
+			}
+
+			mode, err := models.AccessLevel(user.ID, repo)
+			if err != nil {
+				fail("Internal error", "Fail to check access: %v", err)
+			}
+
+			if mode < requestMode {
+				clientMessage := _ACCESS_DENIED_MESSAGE
+				if mode >= models.ACCESS_MODE_READ {
+					clientMessage = "You do not have sufficient authorization for this action"
+				}
+				fail(clientMessage,
+					"User '%s' does not have level '%v' access to repository '%s'",
+					user.Name, requestMode, repoFullName)
+			}
+		}
+	} else {
+		setting.NewService()
+		// Check if the key can access to the repository in case of it is a deploy key (a deploy keys != user key).
+		// A deploy key doesn't represent a signed in user, so in a site with Service.RequireSignInView activated
+		// we should give read access only in repositories where this deploy key is in use. In other case, a server
+		// or system using an active deploy key can get read access to all the repositories in a Gitote service.
+		if key.IsDeployKey() && setting.Service.RequireSignInView {
+			checkDeployKey(key, repo)
+		}
+	}
+
+	// Update user key activity.
+	if key.ID > 0 {
+		key, err := models.GetPublicKeyByID(key.ID)
+		if err != nil {
+			fail("Internal error", "GetPublicKeyByID: %v", err)
+		}
+
+		key.Updated = time.Now()
+		if err = models.UpdatePublicKey(key); err != nil {
+			fail("Internal error", "UpdatePublicKey: %v", err)
+		}
+	}
+
+	// Special handle for Windows.
+	if setting.IsWindows {
+		verb = strings.Replace(verb, "-", " ", 1)
+	}
+
+	var gitCmd *exec.Cmd
+	verbs := strings.Split(verb, " ")
+	if len(verbs) == 2 {
+		gitCmd = exec.Command(verbs[0], verbs[1], repoFullName)
+	} else {
+		gitCmd = exec.Command(verb, repoFullName)
+	}
+	if requestMode == models.ACCESS_MODE_WRITE {
+		gitCmd.Env = append(os.Environ(), http.ComposeHookEnvs(http.ComposeHookEnvsOptions{
+			AuthUser:  user,
+			OwnerName: owner.Name,
+			OwnerSalt: owner.Salt,
+			RepoID:    repo.ID,
+			RepoName:  repo.Name,
+			RepoPath:  repo.RepoPath(),
+		})...)
+	}
+	gitCmd.Dir = setting.RepoRootPath
+	gitCmd.Stdout = os.Stdout
+	gitCmd.Stdin = os.Stdin
+	gitCmd.Stderr = os.Stderr
+	if err = gitCmd.Run(); err != nil {
+		fail("Internal error", "Fail to execute git command: %v", err)
+	}
+
+	return nil
+}

+ 754 - 0
cmd/web.go

@@ -0,0 +1,754 @@
+package cmd
+
+import (
+	"crypto/tls"
+	"fmt"
+	"gitote/gitote/models"
+	"gitote/gitote/pkg/bindata"
+	"gitote/gitote/pkg/context"
+	"gitote/gitote/pkg/form"
+	"gitote/gitote/pkg/mailer"
+	"gitote/gitote/pkg/setting"
+	"gitote/gitote/pkg/template"
+	"gitote/gitote/routes"
+	"gitote/gitote/routes/admin"
+	apiv1 "gitote/gitote/routes/api/v1"
+	"gitote/gitote/routes/dev"
+	"gitote/gitote/routes/org"
+	"gitote/gitote/routes/pages"
+	"gitote/gitote/routes/repo"
+	"gitote/gitote/routes/user"
+	"net"
+	"net/http"
+	"net/http/fcgi"
+	"os"
+	"path"
+	"strings"
+
+	"github.com/Unknwon/com"
+	"github.com/go-macaron/binding"
+	"github.com/go-macaron/cache"
+	"github.com/go-macaron/captcha"
+	"github.com/go-macaron/csrf"
+	"github.com/go-macaron/gzip"
+	"github.com/go-macaron/i18n"
+	"github.com/go-macaron/session"
+	"github.com/go-macaron/toolbox"
+	"github.com/prometheus/client_golang/prometheus/promhttp"
+	"github.com/urfave/cli"
+	log "gopkg.in/clog.v1"
+	"gopkg.in/macaron.v1"
+)
+
+var Web = cli.Command{
+	Name:  "web",
+	Usage: "Start web server",
+	Description: `Gitote web server is the only thing you need to run,
+and it takes care of all the other things for you`,
+	Action: runWeb,
+	Flags: []cli.Flag{
+		stringFlag("port, p", "3000", "Temporary port number to prevent conflict"),
+		stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
+	},
+}
+
+// newMacaron initializes Macaron instance.
+func newMacaron() *macaron.Macaron {
+	m := macaron.New()
+	if !setting.DisableRouterLog {
+		m.Use(macaron.Logger())
+	}
+	m.Use(macaron.Recovery())
+	if setting.EnableGzip {
+		m.Use(gzip.Gziper())
+	}
+	if setting.Protocol == setting.SCHEME_FCGI {
+		m.SetURLPrefix(setting.AppSubURL)
+	}
+	m.Use(macaron.Static(
+		path.Join(setting.StaticRootPath, "public"),
+		macaron.StaticOptions{
+			SkipLogging: setting.DisableRouterLog,
+		},
+	))
+	m.Use(macaron.Static(
+		setting.AvatarUploadPath,
+		macaron.StaticOptions{
+			Prefix:      models.USER_AVATAR_URL_PREFIX,
+			SkipLogging: setting.DisableRouterLog,
+		},
+	))
+	m.Use(macaron.Static(
+		setting.RepositoryAvatarUploadPath,
+		macaron.StaticOptions{
+			Prefix:      models.REPO_AVATAR_URL_PREFIX,
+			SkipLogging: setting.DisableRouterLog,
+		},
+	))
+
+	funcMap := template.NewFuncMap()
+	m.Use(macaron.Renderer(macaron.RenderOptions{
+		Directory:         path.Join(setting.StaticRootPath, "templates"),
+		AppendDirectories: []string{path.Join(setting.CustomPath, "templates")},
+		Funcs:             funcMap,
+		IndentJSON:        macaron.Env != macaron.PROD,
+	}))
+	mailer.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"),
+		path.Join(setting.CustomPath, "templates/mail"), funcMap)
+
+	localeNames, err := bindata.AssetDir("conf/locale")
+	if err != nil {
+		log.Fatal(4, "Fail to list locale files: %v", err)
+	}
+	localFiles := make(map[string][]byte)
+	for _, name := range localeNames {
+		localFiles[name] = bindata.MustAsset("conf/locale/" + name)
+	}
+	m.Use(i18n.I18n(i18n.Options{
+		SubURL:          setting.AppSubURL,
+		Files:           localFiles,
+		CustomDirectory: path.Join(setting.CustomPath, "conf/locale"),
+		Langs:           []string{"en-US", "en-GB"},
+		Names:           []string{"English US", "English UK"},
+		DefaultLang:     "en-US",
+		Redirect:        true,
+	}))
+	m.Use(cache.Cacher(cache.Options{
+		Adapter:       setting.CacheAdapter,
+		AdapterConfig: setting.CacheConn,
+		Interval:      setting.CacheInterval,
+	}))
+	m.Use(captcha.Captchaer(captcha.Options{
+		SubURL: setting.AppSubURL,
+	}))
+	m.Use(session.Sessioner(setting.SessionConfig))
+	m.Use(csrf.Csrfer(csrf.Options{
+		Secret:     setting.SecretKey,
+		Cookie:     setting.CSRFCookieName,
+		SetCookie:  true,
+		Header:     "X-Csrf-Token",
+		CookiePath: setting.AppSubURL,
+	}))
+	m.Use(toolbox.Toolboxer(m, toolbox.Options{
+		HealthCheckFuncs: []*toolbox.HealthCheckFuncDesc{
+			&toolbox.HealthCheckFuncDesc{
+				Desc: "Database connection",
+				Func: models.Ping,
+			},
+		},
+	}))
+	m.Use(context.Contexter())
+	return m
+}
+
+func runWeb(c *cli.Context) error {
+	if c.IsSet("config") {
+		setting.CustomConf = c.String("config")
+	}
+	routes.GlobalInit()
+
+	m := newMacaron()
+
+	reqSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: true})
+	ignSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView})
+	ignSignInAndCsrf := context.Toggle(&context.ToggleOptions{DisableCSRF: true})
+	reqSignOut := context.Toggle(&context.ToggleOptions{SignOutRequired: true})
+
+	bindIgnErr := binding.BindIgnErr
+
+	m.SetAutoHead(true)
+
+	// FIXME: not all routes need go through same middlewares.
+	// Especially some AJAX requests, we can reduce middleware number to improve performance.
+	// Routers.
+	m.Get("/", ignSignIn, routes.Home)
+	m.Get("/trending", routes.ExploreTrending)
+	m.Group("/explore", func() {
+		m.Get("/", routes.ExploreHome)
+		m.Get("/repos", routes.ExploreRepos)
+		m.Get("/users", routes.ExploreUsers)
+		m.Get("/organizations", routes.ExploreOrganizations)
+	}, ignSignIn)
+	m.Combo("/install", routes.InstallInit).Get(routes.Install).
+		Post(bindIgnErr(form.Install{}), routes.InstallPost)
+	m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues)
+
+	// ***** START: User *****
+	m.Group("/user", func() {
+		m.Group("/login", func() {
+			m.Combo("").Get(user.Login).
+				Post(bindIgnErr(form.SignIn{}), user.LoginPost)
+			m.Combo("/two_factor").Get(user.LoginTwoFactor).Post(user.LoginTwoFactorPost)
+			m.Combo("/two_factor_recovery_code").Get(user.LoginTwoFactorRecoveryCode).Post(user.LoginTwoFactorRecoveryCodePost)
+		})
+
+		m.Get("/sign_up", user.SignUp)
+		m.Post("/sign_up", bindIgnErr(form.Register{}), user.SignUpPost)
+		m.Get("/reset_password", user.ResetPasswd)
+		m.Post("/reset_password", user.ResetPasswdPost)
+	}, reqSignOut)
+
+	m.Group("/user/settings", func() {
+		m.Get("", user.Settings)
+		m.Post("", bindIgnErr(form.UpdateProfile{}), user.SettingsPost)
+
+		m.Get("/social", user.SettingsSocial)
+		m.Post("/social", bindIgnErr(form.UpdateSocial{}), user.SettingsSocialPost)
+
+		m.Combo("/avatar").Get(user.SettingsAvatar).
+			Post(binding.MultipartForm(form.Avatar{}), user.SettingsAvatarPost)
+		m.Post("/avatar/delete", user.SettingsDeleteAvatar)
+		m.Combo("/email").Get(user.SettingsEmails).
+			Post(bindIgnErr(form.AddEmail{}), user.SettingsEmailPost)
+		m.Post("/email/delete", user.DeleteEmail)
+		m.Get("/password", user.SettingsPassword)
+		m.Post("/password", bindIgnErr(form.ChangePassword{}), user.SettingsPasswordPost)
+		m.Combo("/ssh").Get(user.SettingsSSHKeys).
+			Post(bindIgnErr(form.AddSSHKey{}), user.SettingsSSHKeysPost)
+		m.Post("/ssh/delete", user.DeleteSSHKey)
+		m.Group("/security", func() {
+			m.Get("", user.SettingsSecurity)
+			m.Combo("/two_factor_enable").Get(user.SettingsTwoFactorEnable).
+				Post(user.SettingsTwoFactorEnablePost)
+			m.Combo("/two_factor_recovery_codes").Get(user.SettingsTwoFactorRecoveryCodes).
+				Post(user.SettingsTwoFactorRecoveryCodesPost)
+			m.Post("/two_factor_disable", user.SettingsTwoFactorDisable)
+		})
+		m.Group("/repositories", func() {
+			m.Get("", user.SettingsRepos)
+			m.Post("/leave", user.SettingsLeaveRepo)
+		})
+		m.Group("/organizations", func() {
+			m.Get("", user.SettingsOrganizations)
+			m.Post("/leave", user.SettingsLeaveOrganization)
+		})
+		m.Combo("/applications").Get(user.SettingsApplications).
+			Post(bindIgnErr(form.NewAccessToken{}), user.SettingsApplicationsPost)
+		m.Post("/applications/delete", user.SettingsDeleteApplication)
+		m.Get("/embeds", user.SettingsEmbeds)
+		m.Route("/delete", "GET,POST", user.SettingsDelete)
+	}, reqSignIn, func(c *context.Context) {
+		c.Data["PageIsUserSettings"] = true
+	})
+
+	m.Group("/user", func() {
+		m.Any("/activate", user.Activate)
+		m.Any("/activate_email", user.ActivateEmail)
+		m.Get("/email2user", user.Email2User)
+		m.Get("/forget_password", user.ForgotPasswd)
+		m.Post("/forget_password", user.ForgotPasswdPost)
+		m.Get("/logout", user.SignOut)
+	})
+	// ***** END: User *****
+
+	reqAdmin := context.Toggle(&context.ToggleOptions{SignInRequired: true, AdminRequired: true})
+
+	// ***** START: Admin *****
+	m.Group("/admin", func() {
+		m.Get("", admin.Dashboard)
+		m.Get("/config", admin.Config)
+		m.Post("/config/test_mail", admin.SendTestMail)
+		m.Get("/monitor", admin.Monitor)
+		m.Get("/inbox", admin.Inbox)
+		m.Get("/logs", admin.Logs)
+		m.Get("/status", admin.Status)
+
+		m.Group("/users", func() {
+			m.Get("", admin.Users)
+			m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(form.AdminCrateUser{}), admin.NewUserPost)
+			m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(form.AdminEditUser{}), admin.EditUserPost)
+			m.Post("/:userid/delete", admin.DeleteUser)
+		})
+
+		m.Group("/orgs", func() {
+			m.Get("", admin.Organizations)
+		})
+
+		m.Group("/repos", func() {
+			m.Get("", admin.Repos)
+			m.Post("/delete", admin.DeleteRepo)
+		})
+
+		m.Group("/auths", func() {
+			m.Get("", admin.Authentications)
+			m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(form.Authentication{}), admin.NewAuthSourcePost)
+			m.Combo("/:authid").Get(admin.EditAuthSource).
+				Post(bindIgnErr(form.Authentication{}), admin.EditAuthSourcePost)
+			m.Post("/:authid/delete", admin.DeleteAuthSource)
+		})
+
+		m.Group("/notices", func() {
+			m.Get("", admin.Notices)
+			m.Post("/delete", admin.DeleteNotices)
+			m.Get("/empty", admin.EmptyNotices)
+		})
+	}, reqAdmin)
+
+	// ***** END: Admin *****
+
+	// ***** START: Pages *****
+	m.Get("/about", ignSignIn, pages.About)
+	m.Get("/faq", ignSignIn, pages.Faq)
+	m.Get("/privacy", ignSignIn, pages.Privacy)
+	m.Get("/tos", ignSignIn, pages.Tos)
+	m.Get("/developers", ignSignIn, pages.Developers)
+	m.Get("/brand", ignSignIn, pages.Brand)
+	m.Get("/contribute", ignSignIn, pages.Contribute)
+	m.Get("/security", ignSignIn, pages.Security)
+	m.Get("/verified", ignSignIn, pages.Verified)
+	m.Get("/makers", ignSignIn, pages.Makers)
+	m.Get("/help", ignSignIn, pages.Help)
+	m.Get("/contact", ignSignIn, pages.Contact)
+	m.Get("/features", ignSignIn, pages.Features)
+	m.Get("/request", ignSignIn, pages.FeatureRequest)
+	m.Get("/sponsorship", ignSignIn, pages.Sponsorship)
+	m.Get("/status", func(c *context.Context) {
+		c.Redirect("https://gitote.hund.io")
+	})
+
+	// ***** END: Pages *****
+
+	// ***** START: Embed *****
+	m.Get("/embed/user/:username", ignSignIn, user.Embed)
+	// ***** END: Embed *****
+
+	m.Group("", func() {
+		m.Group("/:username", func() {
+			m.Get("", user.Profile)
+			m.Get("/followers", user.Followers)
+			m.Get("/following", user.Following)
+			m.Get("/stars", user.Stars)
+		})
+
+		m.Get("/attachments/:uuid", func(c *context.Context) {
+			attach, err := models.GetAttachmentByUUID(c.Params(":uuid"))
+			if err != nil {
+				c.NotFoundOrServerError("GetAttachmentByUUID", models.IsErrAttachmentNotExist, err)
+				return
+			} else if !com.IsFile(attach.LocalPath()) {
+				c.NotFound()
+				return
+			}
+
+			fr, err := os.Open(attach.LocalPath())
+			if err != nil {
+				c.Handle(500, "Open", err)
+				return
+			}
+			defer fr.Close()
+
+			c.Header().Set("Cache-Control", "public,max-age=86400")
+			fmt.Println("attach.Name:", attach.Name)
+			c.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, attach.Name))
+			if err = repo.ServeData(c, attach.Name, fr); err != nil {
+				c.Handle(500, "ServeData", err)
+				return
+			}
+		})
+		m.Post("/issues/attachments", repo.UploadIssueAttachment)
+		m.Post("/releases/attachments", repo.UploadReleaseAttachment)
+	}, ignSignIn)
+
+	m.Group("/:username", func() {
+		m.Get("/action/:action", user.Action)
+	}, reqSignIn)
+
+	if macaron.Env == macaron.DEV {
+		m.Get("/template/*", dev.TemplatePreview)
+	}
+
+	reqRepoAdmin := context.RequireRepoAdmin()
+	reqRepoWriter := context.RequireRepoWriter()
+
+	// ***** START: Organization *****
+	m.Group("/org", func() {
+		m.Group("", func() {
+			m.Get("/create", org.Create)
+			m.Post("/create", bindIgnErr(form.CreateOrg{}), org.CreatePost)
+		}, func(c *context.Context) {
+			if !c.User.CanCreateOrganization() {
+				c.NotFound()
+			}
+		})
+
+		m.Group("/:org", func() {
+			m.Get("/dashboard", user.Dashboard)
+			m.Get("/^:type(issues|pulls)$", user.Issues)
+			m.Get("/members", org.Members)
+			m.Get("/members/action/:action", org.MembersAction)
+
+			m.Get("/teams", org.Teams)
+		}, context.OrgAssignment(true))
+
+		m.Group("/:org", func() {
+			m.Get("/teams/:team", org.TeamMembers)
+			m.Get("/teams/:team/repositories", org.TeamRepositories)
+			m.Route("/teams/:team/action/:action", "GET,POST", org.TeamsAction)
+			m.Route("/teams/:team/action/repo/:action", "GET,POST", org.TeamsRepoAction)
+		}, context.OrgAssignment(true, false, true))
+
+		m.Group("/:org", func() {
+			m.Get("/teams/new", org.NewTeam)
+			m.Post("/teams/new", bindIgnErr(form.CreateTeam{}), org.NewTeamPost)
+			m.Get("/teams/:team/edit", org.EditTeam)
+			m.Post("/teams/:team/edit", bindIgnErr(form.CreateTeam{}), org.EditTeamPost)
+			m.Post("/teams/:team/delete", org.DeleteTeam)
+
+			m.Group("/settings", func() {
+				m.Combo("").Get(org.Settings).
+					Post(bindIgnErr(form.UpdateOrgSetting{}), org.SettingsPost)
+				m.Post("/avatar", binding.MultipartForm(form.Avatar{}), org.SettingsAvatar)
+				m.Post("/avatar/delete", org.SettingsDeleteAvatar)
+
+				m.Group("/hooks", func() {
+					m.Get("", org.Webhooks)
+					m.Post("/delete", org.DeleteWebhook)
+					m.Get("/:type/new", repo.WebhooksNew)
+					m.Post("/gitote/new", bindIgnErr(form.NewWebhook{}), repo.WebHooksNewPost)
+					m.Post("/slack/new", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksNewPost)
+					m.Post("/discord/new", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksNewPost)
+					m.Get("/:id", repo.WebHooksEdit)
+					m.Post("/gitote/:id", bindIgnErr(form.NewWebhook{}), repo.WebHooksEditPost)
+					m.Post("/slack/:id", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksEditPost)
+					m.Post("/discord/:id", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksEditPost)
+				})
+
+				m.Route("/delete", "GET,POST", org.SettingsDelete)
+			})
+
+			m.Route("/invitations/new", "GET,POST", org.Invitation)
+		}, context.OrgAssignment(true, true))
+	}, reqSignIn)
+	// ***** END: Organization *****
+
+	// ***** START: Repository *****
+	m.Group("/repo", func() {
+		m.Get("/create", repo.Create)
+		m.Post("/create", bindIgnErr(form.CreateRepo{}), repo.CreatePost)
+		m.Get("/migrate", repo.Migrate)
+		m.Post("/migrate", bindIgnErr(form.MigrateRepo{}), repo.MigratePost)
+		m.Combo("/fork/:repoid").Get(repo.Fork).
+			Post(bindIgnErr(form.CreateRepo{}), repo.ForkPost)
+	}, reqSignIn)
+
+	m.Group("/:username/:reponame", func() {
+		m.Group("/settings", func() {
+			m.Combo("").Get(repo.Settings).
+				Post(bindIgnErr(form.RepoSetting{}), repo.SettingsPost)
+			m.Combo("/avatar").Get(repo.SettingsAvatar).
+				Post(binding.MultipartForm(form.Avatar{}), repo.SettingsAvatarPost)
+			m.Post("/avatar/delete", repo.SettingsDeleteAvatar)
+			m.Group("/collaboration", func() {
+				m.Combo("").Get(repo.SettingsCollaboration).Post(repo.SettingsCollaborationPost)
+				m.Post("/access_mode", repo.ChangeCollaborationAccessMode)
+				m.Post("/delete", repo.DeleteCollaboration)
+			})
+			m.Group("/branches", func() {
+				m.Get("", repo.SettingsBranches)
+				m.Post("/default_branch", repo.UpdateDefaultBranch)
+				m.Combo("/*").Get(repo.SettingsProtectedBranch).
+					Post(bindIgnErr(form.ProtectBranch{}), repo.SettingsProtectedBranchPost)
+			}, func(c *context.Context) {
+				if c.Repo.Repository.IsMirror {
+					c.NotFound()
+					return
+				}
+			})
+
+			m.Group("/hooks", func() {
+				m.Get("", repo.Webhooks)
+				m.Post("/delete", repo.DeleteWebhook)
+				m.Get("/:type/new", repo.WebhooksNew)
+				m.Post("/gitote/new", bindIgnErr(form.NewWebhook{}), repo.WebHooksNewPost)
+				m.Post("/slack/new", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksNewPost)
+				m.Post("/discord/new", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksNewPost)
+				m.Post("/gitote/:id", bindIgnErr(form.NewWebhook{}), repo.WebHooksEditPost)
+				m.Post("/slack/:id", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksEditPost)
+				m.Post("/discord/:id", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksEditPost)
+
+				m.Group("/:id", func() {
+					m.Get("", repo.WebHooksEdit)
+					m.Post("/test", repo.TestWebhook)
+					m.Post("/redelivery", repo.RedeliveryWebhook)
+				})
+
+				m.Group("/git", func() {
+					m.Get("", repo.SettingsGitHooks)
+					m.Combo("/:name").Get(repo.SettingsGitHooksEdit).
+						Post(repo.SettingsGitHooksEditPost)
+				}, context.GitHookService())
+			})
+
+			m.Group("/keys", func() {
+				m.Combo("").Get(repo.SettingsDeployKeys).
+					Post(bindIgnErr(form.AddSSHKey{}), repo.SettingsDeployKeysPost)
+				m.Post("/delete", repo.DeleteDeployKey)
+			})
+
+		}, func(c *context.Context) {
+			c.Data["PageIsSettings"] = true
+		})
+	}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef())
+
+	m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action)
+	m.Group("/:username/:reponame", func() {
+		m.Get("/issues", repo.RetrieveLabels, repo.Issues)
+		m.Get("/issues/:index", repo.ViewIssue)
+		m.Get("/labels/", repo.RetrieveLabels, repo.Labels)
+		m.Get("/milestones", repo.Milestones)
+	}, ignSignIn, context.RepoAssignment(true))
+	m.Group("/:username/:reponame", func() {
+		// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
+		// So they can apply their own enable/disable logic on routers.
+		m.Group("/issues", func() {
+			m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue).
+				Post(bindIgnErr(form.NewIssue{}), repo.NewIssuePost)
+
+			m.Group("/:index", func() {
+				m.Post("/title", repo.UpdateIssueTitle)
+				m.Post("/content", repo.UpdateIssueContent)
+				m.Combo("/comments").Post(bindIgnErr(form.CreateComment{}), repo.NewComment)
+			})
+		})
+		m.Group("/comments/:id", func() {
+			m.Post("", repo.UpdateCommentContent)
+			m.Post("/delete", repo.DeleteComment)
+		})
+	}, reqSignIn, context.RepoAssignment(true))
+	m.Group("/:username/:reponame", func() {
+		m.Group("/wiki", func() {
+			m.Get("/?:page", repo.Wiki)
+			m.Get("/_pages", repo.WikiPages)
+		}, repo.MustEnableWiki, context.RepoRef())
+	}, ignSignIn, context.RepoAssignment(false, true))
+
+	m.Group("/:username/:reponame", func() {
+		// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
+		// So they can apply their own enable/disable logic on routers.
+		m.Group("/issues", func() {
+			m.Group("/:index", func() {
+				m.Post("/label", repo.UpdateIssueLabel)
+				m.Post("/milestone", repo.UpdateIssueMilestone)
+				m.Post("/assignee", repo.UpdateIssueAssignee)
+			}, reqRepoWriter)
+		})
+		m.Group("/labels", func() {
+			m.Post("/new", bindIgnErr(form.CreateLabel{}), repo.NewLabel)
+			m.Post("/edit", bindIgnErr(form.CreateLabel{}), repo.UpdateLabel)
+			m.Post("/delete", repo.DeleteLabel)
+			m.Post("/initialize", bindIgnErr(form.InitializeLabels{}), repo.InitializeLabels)
+		}, reqRepoWriter, context.RepoRef())
+		m.Group("/milestones", func() {
+			m.Combo("/new").Get(repo.NewMilestone).
+				Post(bindIgnErr(form.CreateMilestone{}), repo.NewMilestonePost)
+			m.Get("/:id/edit", repo.EditMilestone)
+			m.Post("/:id/edit", bindIgnErr(form.CreateMilestone{}), repo.EditMilestonePost)
+			m.Get("/:id/:action", repo.ChangeMilestonStatus)
+			m.Post("/delete", repo.DeleteMilestone)
+		}, reqRepoWriter, context.RepoRef())
+
+		m.Group("/releases", func() {
+			m.Get("/new", repo.NewRelease)
+			m.Post("/new", bindIgnErr(form.NewRelease{}), repo.NewReleasePost)
+			m.Post("/delete", repo.DeleteRelease)
+			m.Get("/edit/*", repo.EditRelease)
+			m.Post("/edit/*", bindIgnErr(form.EditRelease{}), repo.EditReleasePost)
+		}, repo.MustBeNotBare, reqRepoWriter, func(c *context.Context) {
+			c.Data["PageIsViewFiles"] = true
+		})
+
+		// FIXME: Should use c.Repo.PullRequest to unify template, currently we have inconsistent URL
+		// for PR in same repository. After select branch on the page, the URL contains redundant head user name.
+		// e.g. /org1/test-repo/compare/master...org1:develop
+		// which should be /org1/test-repo/compare/master...develop
+		m.Combo("/compare/*", repo.MustAllowPulls).Get(repo.CompareAndPullRequest).
+			Post(bindIgnErr(form.NewIssue{}), repo.CompareAndPullRequestPost)
+
+		m.Group("", func() {
+			m.Combo("/_edit/*").Get(repo.EditFile).
+				Post(bindIgnErr(form.EditRepoFile{}), repo.EditFilePost)
+			m.Combo("/_new/*").Get(repo.NewFile).
+				Post(bindIgnErr(form.EditRepoFile{}), repo.NewFilePost)
+			m.Post("/_preview/*", bindIgnErr(form.EditPreviewDiff{}), repo.DiffPreviewPost)
+			m.Combo("/_delete/*").Get(repo.DeleteFile).
+				Post(bindIgnErr(form.DeleteRepoFile{}), repo.DeleteFilePost)
+
+			m.Group("", func() {
+				m.Combo("/_upload/*").Get(repo.UploadFile).
+					Post(bindIgnErr(form.UploadRepoFile{}), repo.UploadFilePost)
+				m.Post("/upload-file", repo.UploadFileToServer)
+				m.Post("/upload-remove", bindIgnErr(form.RemoveUploadFile{}), repo.RemoveUploadFileFromServer)
+			}, func(c *context.Context) {
+				if !setting.Repository.Upload.Enabled {
+					c.NotFound()
+					return
+				}
+			})
+		}, repo.MustBeNotBare, reqRepoWriter, context.RepoRef(), func(c *context.Context) {
+			if !c.Repo.CanEnableEditor() {
+				c.NotFound()
+				return
+			}
+
+			c.Data["PageIsViewFiles"] = true
+		})
+	}, reqSignIn, context.RepoAssignment())
+
+	m.Group("/:username/:reponame", func() {
+		m.Group("", func() {
+			m.Get("/releases", repo.MustBeNotBare, repo.Releases)
+			m.Get("/pulls", repo.RetrieveLabels, repo.Pulls)
+			m.Get("/pulls/:index", repo.ViewPull)
+		}, context.RepoRef())
+
+		m.Group("/branches", func() {
+			m.Get("", repo.Branches)
+			m.Get("/all", repo.AllBranches)
+			m.Post("/delete/*", reqSignIn, reqRepoWriter, repo.DeleteBranchPost)
+		}, repo.MustBeNotBare, func(c *context.Context) {
+			c.Data["PageIsViewFiles"] = true
+		})
+
+		m.Group("/wiki", func() {
+			m.Group("", func() {
+				m.Combo("/_new").Get(repo.NewWiki).
+					Post(bindIgnErr(form.NewWiki{}), repo.NewWikiPost)
+				m.Combo("/:page/_edit").Get(repo.EditWiki).
+					Post(bindIgnErr(form.NewWiki{}), repo.EditWikiPost)
+				m.Post("/:page/delete", repo.DeleteWikiPagePost)
+			}, reqSignIn, reqRepoWriter)
+		}, repo.MustEnableWiki, context.RepoRef())
+
+		m.Get("/archive/*", repo.MustBeNotBare, repo.Download)
+
+		m.Group("/pulls/:index", func() {
+			m.Get("/commits", context.RepoRef(), repo.ViewPullCommits)
+			m.Get("/files", context.RepoRef(), repo.ViewPullFiles)
+			m.Post("/merge", reqRepoWriter, repo.MergePullRequest)
+		}, repo.MustAllowPulls)
+
+		m.Group("", func() {
+			m.Get("/src/*", repo.Home)
+			m.Get("/raw/*", repo.SingleDownload)
+			m.Get("/commits/*", repo.RefCommits)
+			m.Get("/commit/:sha([a-f0-9]{7,40})$", repo.Diff)
+			m.Get("/forks", repo.Forks)
+		}, repo.MustBeNotBare, context.RepoRef())
+		m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.MustBeNotBare, repo.RawDiff)
+
+		m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.MustBeNotBare, context.RepoRef(), repo.CompareDiff)
+	}, ignSignIn, context.RepoAssignment())
+	m.Group("/:username/:reponame", func() {
+		m.Get("/stars", repo.Stars)
+		m.Get("/watchers", repo.Watchers)
+	}, ignSignIn, context.RepoAssignment(), context.RepoRef())
+
+	m.Group("/:username", func() {
+		m.Get("/:reponame", ignSignIn, context.RepoAssignment(), context.RepoRef(), repo.Home)
+
+		m.Group("/:reponame", func() {
+			m.Head("/tasks/trigger", repo.TriggerTask)
+		})
+		// Use the regexp to match the repository name
+		// Duplicated routes to enable different ways of accessing same set of URLs,
+		// e.g. with or without ".git" suffix.
+		m.Group("/:reponame([\\d\\w-_\\.]+\\.git$)", func() {
+			m.Get("", ignSignIn, context.RepoAssignment(), context.RepoRef(), repo.Home)
+			m.Options("/*", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
+			m.Route("/*", "GET,POST", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
+		})
+		m.Options("/:reponame/*", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
+		m.Route("/:reponame/*", "GET,POST", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
+	})
+	// ***** END: Repository *****
+
+	m.Group("/api", func() {
+		apiv1.RegisterRoutes(m)
+	}, ignSignIn)
+
+	m.Group("/-", func() {
+		if setting.Prometheus.Enabled {
+			m.Get("/metrics", func(c *context.Context) {
+				if !setting.Prometheus.EnableBasicAuth {
+					return
+				}
+
+				c.RequireBasicAuth(setting.Prometheus.BasicAuthUsername, setting.Prometheus.BasicAuthPassword)
+			}, promhttp.Handler())
+		}
+	})
+
+	// Not found handler.
+	m.NotFound(routes.NotFound)
+
+	// Flag for port number in case first time run conflict.
+	if c.IsSet("port") {
+		setting.AppURL = strings.Replace(setting.AppURL, setting.HTTPPort, c.String("port"), 1)
+		setting.HTTPPort = c.String("port")
+	}
+
+	var listenAddr string
+	if setting.Protocol == setting.SCHEME_UNIX_SOCKET {
+		listenAddr = fmt.Sprintf("%s", setting.HTTPAddr)
+	} else {
+		listenAddr = fmt.Sprintf("%s:%s", setting.HTTPAddr, setting.HTTPPort)
+	}
+	log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL)
+
+	var err error
+	switch setting.Protocol {
+	case setting.SCHEME_HTTP:
+		err = http.ListenAndServe(listenAddr, m)
+	case setting.SCHEME_HTTPS:
+		var tlsMinVersion uint16
+		switch setting.TLSMinVersion {
+		case "SSL30":
+			tlsMinVersion = tls.VersionSSL30
+		case "TLS12":
+			tlsMinVersion = tls.VersionTLS12
+		case "TLS11":
+			tlsMinVersion = tls.VersionTLS11
+		case "TLS10":
+			fallthrough
+		default:
+			tlsMinVersion = tls.VersionTLS10
+		}
+		server := &http.Server{Addr: listenAddr, TLSConfig: &tls.Config{
+			MinVersion:               tlsMinVersion,
+			CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
+			PreferServerCipherSuites: true,
+			CipherSuites: []uint16{
+				tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // Required for HTTP/2 support.
+				tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+				tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+			},
+		}, Handler: m}
+		err = server.ListenAndServeTLS(setting.CertFile, setting.KeyFile)
+	case setting.SCHEME_FCGI:
+		err = fcgi.Serve(nil, m)
+	case setting.SCHEME_UNIX_SOCKET:
+		os.Remove(listenAddr)
+
+		var listener *net.UnixListener
+		listener, err = net.ListenUnix("unix", &net.UnixAddr{listenAddr, "unix"})
+		if err != nil {
+			break // Handle error after switch
+		}
+
+		// FIXME: add proper implementation of signal capture on all protocols
+		// execute this on SIGTERM or SIGINT: listener.Close()
+		if err = os.Chmod(listenAddr, os.FileMode(setting.UnixSocketPermission)); err != nil {
+			log.Fatal(4, "Failed to set permission of unix socket: %v", err)
+		}
+		err = http.Serve(listener, m)
+	default:
+		log.Fatal(4, "Invalid protocol: %s", setting.Protocol)
+	}
+
+	if err != nil {
+		log.Fatal(4, "Failed to start server: %v", err)
+	}
+
+	return nil
+}

+ 9 - 0
conf/README.md

@@ -0,0 +1,9 @@
+Execute following command in ROOT directory when anything is changed:
+
+```sh
+# Download Bindata
+$ wget https://gitlab.com/gitote/bindata/raw/master/go-bindata
+
+# Build Bindata
+$ make bindata
+```

+ 479 - 0
conf/app.ini

@@ -0,0 +1,479 @@
+; App name that shows on every page title
+APP_NAME = Gitote
+; The name of the system user that runs Gitote
+RUN_USER = git
+; Either "dev", "prod" or "test"
+RUN_MODE = dev
+
+[server]
+PROTOCOL = http
+DOMAIN = localhost
+ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
+HTTP_ADDR = 0.0.0.0
+HTTP_PORT = 3000
+; Permission for unix socket
+UNIX_SOCKET_PERMISSION = 666
+; Local (DMZ) URL for Gitote workers (such as SSH update) accessing web service.
+; In most cases you do not need to change the default value.
+; Alter it only if your SSH server node is not the same as HTTP node.
+LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
+; Disable SSH feature when not available
+DISABLE_SSH = false
+; Whether use builtin SSH server or not.
+START_SSH_SERVER = false
+; Domain name to be exposed in SSH clone URL
+SSH_DOMAIN = %(DOMAIN)s
+; Port number to be exposed in SSH clone URL
+SSH_PORT = 22
+; Network interface builtin SSH server listens on
+SSH_LISTEN_HOST = 0.0.0.0
+; Port number builtin SSH server listens on
+SSH_LISTEN_PORT = %(SSH_PORT)s
+; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
+SSH_ROOT_PATH =
+; Indicate whether to rewrite authorized_keys at start, ignored when use builtin SSH server
+REWRITE_AUTHORIZED_KEYS_AT_START = false
+; Choose the ciphers to support for SSH connections
+SSH_SERVER_CIPHERS = aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, arcfour256, arcfour128
+; Directory to create temporary files when test publick key using ssh-keygen,
+; default is system temporary directory.
+SSH_KEY_TEST_PATH =
+; Path to ssh-keygen, default is 'ssh-keygen' and let shell find out which one to call.
+SSH_KEYGEN_PATH = ssh-keygen
+; Indicate whether to check minimum key size with corresponding type
+MINIMUM_KEY_SIZE_CHECK = false
+; Disable CDN even in "prod" mode
+OFFLINE_MODE = false
+DISABLE_ROUTER_LOG = false
+; Generate steps:
+; $ ./gitote cert -ca=true -duration=8760h0m0s -host=myhost.example.com
+;
+; Or from a .pfx file exported from the Windows certificate store (do
+; not forget to export the private key):
+; $ openssl pkcs12 -in cert.pfx -out cert.pem -nokeys
+; $ openssl pkcs12 -in cert.pfx -out key.pem -nocerts -nodes
+CERT_FILE = custom/https/cert.pem
+KEY_FILE = custom/https/key.pem
+; Allowed TLS version values: SSL30, TLS10, TLS11, TLS12
+TLS_MIN_VERSION = TLS10
+
+; Upper level of template and static file path
+; default is the path where Gitote is executed
+STATIC_ROOT_PATH =
+; Default path for App data
+APP_DATA_PATH = data
+; Application level GZIP support
+ENABLE_GZIP = false
+; Landing page for non-logged users, can be "home" or "explore"
+LANDING_PAGE = home
+
+[repository]
+; Root path for storing repositories's data, default is "~/<username>/gitote-repositories"
+ROOT =
+; The script type server supports, sometimes could be "sh"
+SCRIPT_TYPE = bash
+; Default ANSI charset for an unrecognized charset
+ANSI_CHARSET =
+; Force every new repository to be private
+FORCE_PRIVATE = false
+; Global maximum creation limit of repository per user, -1 means no limit
+MAX_CREATION_LIMIT = -1
+; Mirror sync queue length, increase if mirror syncing starts hanging
+MIRROR_QUEUE_LENGTH = 1000
+; Patch test queue length, increase if pull request patch testing starts hanging
+PULL_REQUEST_QUEUE_LENGTH = 1000
+; Preferred Licenses to place at the top of the list
+; Name must match file name in conf/license or custom/conf/license
+PREFERRED_LICENSES = Apache License 2.0,MIT License
+; Disable ability to interact with repositories by HTTP protocol
+DISABLE_HTTP_GIT = false
+; Enable ability to migrate repository by local path
+ENABLE_LOCAL_PATH_MIGRATION = false
+; Concurrency is used to retrieve commits information. This variable define
+; the maximum number of tasks that can be run at the same time. Usually, the
+; value depend of how many CPUs (cores) you have. If the value is set to zero
+; or under, GITOTE will automatically detect the number of CPUs your system have
+COMMITS_FETCH_CONCURRENCY = 0
+; Enable render mode for raw file
+ENABLE_RAW_FILE_RENDER_MODE = false
+
+[repository.editor]
+; List of file extensions that should have line wraps in the CodeMirror editor.
+; Separate extensions with a comma. To line wrap files without extension, just put a comma
+LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,
+; Valid file modes that have a preview API associated with them, such as api/v1/markdown.
+; Separate values by commas. Preview tab in edit mode won't show if the file extension doesn't match
+PREVIEWABLE_FILE_MODES = markdown
+
+[repository.upload]
+; Enable repository file uploads.
+ENABLED = true
+; Path to temporarily store uploads (default path gets cleaned by Gitote in every start)
+TEMP_PATH = data/tmp/uploads
+; File types that are allowed to be uploaded, e.g. image/jpeg|image/png. Leave empty means allow any file type
+ALLOWED_TYPES =
+; Maximum size of each file in MB
+FILE_MAX_SIZE = 3
+; Maximum number of files per upload
+MAX_FILES = 5
+
+; Attachment settings for releases
+[release.attachment]
+; Whether attachments are enabled. Defaults to `true`
+ENABLED = true
+; Path for attachments. Defaults to `data/attachments`
+PATH = data/attachments
+; One or more allowed types, e.g. image/jpeg|image/png
+ALLOWED_TYPES = */*
+; Max size of each file. Defaults to 32MB
+MAX_SIZE = 32
+; Max number of files per upload. Defaults to 10
+MAX_FILES = 10
+
+[markdown]
+; Enable hard line break extension
+ENABLE_HARD_LINE_BREAK = false
+; List of custom URL-Schemes that are allowed as links when rendering Markdown
+; for example git,magnet
+CUSTOM_URL_SCHEMES =
+; List of file extensions that should be rendered/edited as Markdown
+; Separate extensions with a comma. To render files w/o extension as markdown, just put a comma
+FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
+
+[smartypants]
+ENABLED = false
+FRACTIONS = true
+DASHES = true
+LATEX_DASHES = true
+ANGLED_QUOTES = true
+
+[http]
+; Value for Access-Control-Allow-Origin header, default is not to present
+ACCESS_CONTROL_ALLOW_ORIGIN =
+
+; Define allowed algorithms and their minimum key length (use -1 to disable a type)
+[ssh.minimum_key_sizes]
+ED25519 = 256
+ECDSA   = 256
+RSA     = 2048
+DSA     = 1024
+
+[database]
+; Either "mysql", "postgres" or "sqlite3", you can connect to TiDB with MySQL protocol
+DB_TYPE = mysql
+HOST = 127.0.0.1:3306
+NAME = gitote
+USER = root
+PASSWD =
+; For "postgres" only, either "disable", "require" or "verify-full"
+SSL_MODE = disable
+; For "sqlite3" and "tidb", use absolute path when you start as service
+PATH = data/gitote.db
+
+[admin]
+; Disable regular (non-admin) users to create organizations
+DISABLE_REGULAR_ORG_CREATION = false
+
+[security]
+INSTALL_LOCK = false
+; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
+SECRET_KEY = !#@FDEWREWR&*(
+; Auto-login remember days
+LOGIN_REMEMBER_DAYS = 7
+COOKIE_USERNAME = gitote_awesome
+COOKIE_REMEMBER_NAME = gitote_incredible
+COOKIE_SECURE = false
+; Reverse proxy authentication header name of user name
+REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
+; Enable to set cookie to indicate user login status
+ENABLE_LOGIN_STATUS_COOKIE = false
+LOGIN_STATUS_COOKIE_NAME = login_status
+
+[service]
+ACTIVE_CODE_LIVE_MINUTES = 180
+RESET_PASSWD_CODE_LIVE_MINUTES = 180
+; User need to confirm e-mail for registration
+REGISTER_EMAIL_CONFIRM = false
+; Does not allow register and admin create account only
+DISABLE_REGISTRATION = false
+; User must sign in to view anything.
+REQUIRE_SIGNIN_VIEW = false
+; Mail notification
+ENABLE_NOTIFY_MAIL = false
+ENABLE_REVERSE_PROXY_AUTHENTICATION = false
+ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
+; Enable captcha validation for registration
+ENABLE_CAPTCHA = true
+
+[webhook]
+; Types are enabled for users to use, can be "gitote", "slack", "discord"
+TYPES = gitote, slack, discord
+; Hook task queue length, increase if webhook shooting starts hanging
+QUEUE_LENGTH = 1000
+; Deliver timeout in seconds
+DELIVER_TIMEOUT = 15
+; Allow insecure certification
+SKIP_TLS_VERIFY = false
+; Number of history information in each page
+PAGING_NUM = 10
+
+[mailer]
+ENABLED = false
+; Buffer length of channel, keep it as it is if you don't know what it is.
+SEND_BUFFER_LEN = 100
+; Prefix prepended to the subject line
+SUBJECT_PREFIX = `[%(APP_NAME)s] `
+; Mail server
+; Gmail: smtp.gmail.com:587
+; QQ: smtp.qq.com:465
+; Note, if the port ends with "465", SMTPS will be used. Using STARTTLS on port 587 is recommended per RFC 6409. If the server supports STARTTLS it will always be used.
+HOST =
+; Disable HELO operation when hostname are different.
+DISABLE_HELO =
+; Custom hostname for HELO operation, default is from system.
+HELO_HOSTNAME =
+; Do not verify the certificate of the server. Only use this for self-signed certificates
+SKIP_VERIFY =
+; Use client certificate
+USE_CERTIFICATE = false
+CERT_FILE = custom/mailer/cert.pem
+KEY_FILE = custom/mailer/key.pem
+; Mail from address, RFC 5322. This can be just an email address, or the `"Name" <email@example.com>` format
+FROM =
+; Mailer user name and password
+USER =
+PASSWD =
+; Use text/plain as format of content
+USE_PLAIN_TEXT = false
+
+[cache]
+; Either "memory", "redis", or "memcache", default is "memory"
+ADAPTER = memory
+; For "memory" only, GC interval in seconds, default is 60
+INTERVAL = 60
+; For "redis" and "memcache", connection host address
+; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
+; memcache: `127.0.0.1:11211`
+HOST =
+
+[session]
+; Either "memory", "file", or "redis", default is "memory"
+PROVIDER = memory
+; Provider config options
+; memory: not have any config yet
+; file: session file path, e.g. `data/sessions`
+; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
+; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
+PROVIDER_CONFIG = data/sessions
+; Session cookie name
+COOKIE_NAME = gitote_sess
+; If you use session in https only, default is false
+COOKIE_SECURE = false
+; Enable set cookie, default is true
+ENABLE_SET_COOKIE = true
+; Session GC time interval, default is 3600
+GC_INTERVAL_TIME = 3600
+; Session life time, default is 86400
+SESSION_LIFE_TIME = 86400
+; Cookie name for CSRF
+CSRF_COOKIE_NAME = _csrf
+
+[picture]
+; Path to store user uploaded avatars
+AVATAR_UPLOAD_PATH = data/avatars
+; Path to store repository uploaded avatars
+REPOSITORY_AVATAR_UPLOAD_PATH = data/repo-avatars
+; Chinese users can choose "duoshuo"
+; or a custom avatar source, like: http://cn.gravatar.com/avatar/
+GRAVATAR_SOURCE = gravatar
+; This value will be forced to be true in offline mode.
+DISABLE_GRAVATAR = false
+; Federated avatar lookup uses DNS to discover avatar associated
+; with emails, see https://www.libravatar.org
+; This value will be forced to be false in offline mode or Gravatar is disbaled.
+ENABLE_FEDERATED_AVATAR = false
+
+; Attachment settings for issues
+[attachment]
+; Whether attachments are enabled. Defaults to `true`
+ENABLED = true
+; Path for attachments. Defaults to `data/attachments`
+PATH = data/attachments
+; One or more allowed types, e.g. image/jpeg|image/png
+ALLOWED_TYPES = image/jpeg|image/png
+; Max size of each file. Defaults to 4MB
+MAX_SIZE = 4
+; Max number of files per upload. Defaults to 5
+MAX_FILES = 5
+
+[time]
+; Specifies the format for fully outputed dates. Defaults to RFC1123
+; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
+; For more information about the format see http://golang.org/pkg/time/#pkg-constants
+FORMAT =
+
+; General settings of loggers
+[log]
+ROOT_PATH =
+; Can be "console" and "file", default is "console"
+; Use comma to separate multiple modes, e.g. "console, file, discord, slack"
+MODE = console
+; Buffer length of channel, keep it as it is if you don't know what it is.
+BUFFER_LEN = 100
+; Either "Trace", "Info", "Warn", "Error", "Fatal", default is "Trace"
+LEVEL = Trace
+
+; For "console" mode only
+[log.console]
+; leave empty to inherit
+LEVEL =
+
+; For "file" mode only
+[log.file]
+; leave empty to inherit
+LEVEL =
+; This enables automated log rotate (switch of following options)
+LOG_ROTATE = true
+; Segment log daily
+DAILY_ROTATE = true
+; Max size shift of single file, default is 28 means 1 << 28, 256MB
+MAX_SIZE_SHIFT = 28
+; Max line number of single file
+MAX_LINES = 1000000
+; Expired days of log file (delete after max days)
+MAX_DAYS = 7
+
+; For "slack" mode only
+[log.slack]
+; leave empty to inherit
+LEVEL =
+; Webhook URL
+URL =
+
+[log.discord]
+; leave empty to inherit
+LEVEL =
+; Webhook URL
+URL =
+; Username displayed in webhook
+USERNAME = %(APP_NAME)s
+
+[log.xorm]
+; Enable file rotation
+ROTATE = true
+; Rotate every day
+ROTATE_DAILY = true
+; Rotate once file size excesses x MB
+MAX_SIZE = 100
+; Maximum days to keep logger files
+MAX_DAYS = 3
+
+[cron]
+; Enable running cron tasks periodically.
+ENABLED = true
+; Run cron tasks when Gitote starts.
+RUN_AT_START = false
+
+; Update mirrors
+[cron.update_mirrors]
+SCHEDULE = @every 10m
+
+; Repository health check
+[cron.repo_health_check]
+SCHEDULE = @every 24h
+TIMEOUT = 60s
+; Arguments for command 'git fsck', e.g. "--unreachable --tags"
+; see more on http://git-scm.com/docs/git-fsck/1.7.5
+ARGS =
+
+; Check repository statistics
+[cron.check_repo_stats]
+RUN_AT_START = true
+SCHEDULE = @every 24h
+
+; Cleanup repository archives
+[cron.repo_archive_cleanup]
+RUN_AT_START = false
+SCHEDULE = @every 24h
+; Time duration to check if archive should be cleaned
+OLDER_THAN = 24h
+
+[git]
+; Disables highlight of added and removed changes
+DISABLE_DIFF_HIGHLIGHT = false
+; Max number of lines allowed of a single file in diff view
+MAX_GIT_DIFF_LINES = 1000
+; Max number of characters of a line allowed in diff view
+MAX_GIT_DIFF_LINE_CHARACTERS = 500
+; Max number of files shown in diff view
+MAX_GIT_DIFF_FILES = 100
+; Arguments for command 'git gc', e.g. "--aggressive --auto"
+; see more on http://git-scm.com/docs/git-gc/1.7.5
+GC_ARGS =
+
+; Operation timeout in seconds
+[git.timeout]
+MIGRATE = 600
+MIRROR = 300
+CLONE = 300
+PULL = 300
+GC = 60
+
+[mirror]
+; Default interval in hours between each check
+DEFAULT_INTERVAL = 8
+
+[api]
+; Max number of items will response in a page
+MAX_RESPONSE_ITEMS = 50
+
+[ui]
+; Number of repositories that are showed in one explore page
+EXPLORE_PAGING_NUM = 20
+; Number of issues that are showed in one page
+ISSUE_PAGING_NUM = 10
+; Number of maximum commits showed in one activity feed
+FEED_MAX_COMMIT_NUM = 5
+; Max size in bytes of files to be displayed (default is 8MB)
+MAX_DISPLAY_FILE_SIZE = 8388608
+
+[ui.admin]
+; Number of users that are showed in one page
+USER_PAGING_NUM = 50
+; Number of repos that are showed in one page
+REPO_PAGING_NUM = 50
+; Number of notices that are showed in one page
+NOTICE_PAGING_NUM = 25
+; Number of organization that are showed in one page
+ORG_PAGING_NUM = 50
+
+[ui.user]
+; Number of repos that are showed in one page
+REPO_PAGING_NUM = 15
+; Number of news feeds that are showed in one page
+NEWS_FEED_PAGING_NUM = 20
+; Number of commits that are showed in one page
+COMMITS_PAGING_NUM = 30
+
+[prometheus]
+ENABLED = true
+ENABLE_BASIC_AUTH = false
+BASIC_AUTH_USERNAME =
+BASIC_AUTH_PASSWORD =
+
+[i18n]
+LANGS = en-US,en-GB
+NAMES = English US,English UK
+
+; Used for datetimepicker
+[i18n.datelang]
+en-US = en
+en-GB = en-GB
+
+; Extension mapping to highlight class
+; e.g. .toml=ini
+[highlight.mapping]
+
+[apis]
+; Show Issues count and Build Status in Adminbar https://gitlab.com/profile/personal_access_tokens
+GITLAB_ACCESS_TOKEN = 

+ 28 - 0
conf/auth.d/ldap_bind_dn.conf.example

@@ -0,0 +1,28 @@
+# This is an example of LDAP (BindDN) authentication
+#
+id           = 101
+type         = ldap_bind_dn
+name         = LDAP BindDN
+is_activated = true
+
+[config]
+host               = mydomain.com
+port               = 636
+# 0 - Unencrypted, 1 - LDAPS, 2 - StartTLS
+security_protocol  = 0
+skip_verify        = false
+bind_dn            = 
+bind_password      = 
+user_base          = ou=Users,dc=mydomain,dc=com
+attribute_username = 
+attribute_name     = 
+attribute_surname  = 
+attribute_mail     = mail
+attributes_in_bind = false
+filter             = (&(objectClass=posixAccount)(cn=%s))
+admin_filter       = 
+group_enabled      = false
+group_dn           = 
+group_filter       = 
+group_member_uid   = 
+user_uid           = 

+ 29 - 0
conf/auth.d/ldap_simple_auth.conf.example

@@ -0,0 +1,29 @@
+# This is an example of LDAP (simple auth) authentication
+#
+id           = 102
+type         = ldap_simple_auth
+name         = LDAP Simple Auth
+is_activated = true
+
+[config]
+host               = mydomain.com
+port               = 636
+# 0 - Unencrypted, 1 - LDAPS, 2 - StartTLS
+security_protocol  = 0
+skip_verify        = false
+bind_dn            = 
+bind_password      = 
+user_base          = 
+user_dn            = cn=%s,ou=Users,dc=mydomain,dc=com
+attribute_username = 
+attribute_name     = 
+attribute_surname  = 
+attribute_mail     = mail
+attributes_in_bind = false
+filter             = (&(objectClass=posixAccount)(cn=%s))
+admin_filter       = 
+group_enabled      = false
+group_dn           = 
+group_filter       = 
+group_member_uid   = 
+user_uid           = 

+ 9 - 0
conf/auth.d/pam.conf.example

@@ -0,0 +1,9 @@
+# This is an example of PAM authentication
+#
+id           = 104
+type         = pam
+name         = System Auth
+is_activated = true
+
+[config]
+service_name = system-auth

+ 15 - 0
conf/auth.d/smtp.conf.example

@@ -0,0 +1,15 @@
+# This is an example of SMTP authentication
+#
+id           = 103
+type         = smtp
+name         = GMail
+is_activated = true
+
+[config]
+# Either "PLAIN" or "LOGIN"
+auth            = PLAIN
+host            = smtp.gmail.com
+port            = 587
+allowed_domains = 
+tls             = true
+skip_verify     = false

+ 11 - 0
conf/gitignore/Actionscript

@@ -0,0 +1,11 @@
+# Build and Release Folders
+bin/
+bin-debug/
+bin-release/
+
+# Other files and folders
+.settings/
+
+# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
+# should NOT be excluded as they contain compiler settings and other important
+# information for Eclipse / Flash Builder.

+ 5 - 0
conf/gitignore/Ada

@@ -0,0 +1,5 @@
+# Object file
+*.o
+
+# Ada Library Information
+*.ali

+ 1 - 0
conf/gitignore/Agda

@@ -0,0 +1 @@
+*.agdai

+ 32 - 0
conf/gitignore/Android

@@ -0,0 +1,32 @@
+# Built application files
+*.apk
+*.ap_
+
+# Files for the Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/

+ 3 - 0
conf/gitignore/Anjuta

@@ -0,0 +1,3 @@
+# Local configuration folder and symbol database
+/.anjuta/
+/.anjuta_sym_db.db

+ 2 - 0
conf/gitignore/AppEngine

@@ -0,0 +1,2 @@
+# Google App Engine generated folder
+appengine-generated/

+ 3 - 0
conf/gitignore/AppceleratorTitanium

@@ -0,0 +1,3 @@
+# Build folder and log file
+build/
+build.log

+ 13 - 0
conf/gitignore/ArchLinuxPackages

@@ -0,0 +1,13 @@
+*.tar
+*.tar.*
+*.jar
+*.exe
+*.msi
+*.zip
+*.tgz
+*.log
+*.log.*
+*.sig
+
+pkg/
+src/

+ 27 - 0
conf/gitignore/Archives

@@ -0,0 +1,27 @@
+# It's better to unpack these files and commit the raw source because
+# git has its own built in compression methods.
+*.7z
+*.jar
+*.rar
+*.zip
+*.gz
+*.bzip
+*.bz2
+*.xz
+*.lzma
+*.cab
+
+#packing-only formats
+*.iso
+*.tar
+
+#package management formats
+*.dmg
+*.xpi
+*.gem
+*.egg
+*.deb
+*.rpm
+*.msi
+*.msm
+*.msp

+ 14 - 0
conf/gitignore/Autotools

@@ -0,0 +1,14 @@
+# http://www.gnu.org/software/automake
+
+Makefile.in
+
+# http://www.gnu.org/software/autoconf
+
+/autom4te.cache
+/aclocal.m4
+/compile
+/configure
+/depcomp
+/install-sh
+/missing
+/stamp-h1

+ 4 - 0
conf/gitignore/BricxCC

@@ -0,0 +1,4 @@
+# Bricx Command Center IDE
+# http://bricxcc.sourceforge.net
+*.bak
+*.sym

+ 32 - 0
conf/gitignore/C

@@ -0,0 +1,32 @@
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/

+ 108 - 0
conf/gitignore/C Sharp

@@ -0,0 +1,108 @@
+# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
+[Bb]in/
+[Oo]bj/
+
+# mstest test results
+TestResults
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+[Dd]ebug/
+[Rr]elease/
+x64/
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.log
+*.vspscc
+*.vssscc
+.builds
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*
+
+# NCrunch
+*.ncrunch*
+.*crunch*.local.xml
+
+# Installshield output folder
+[Ee]xpress
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish
+
+# Publish Web Output
+*.Publish.xml
+
+# NuGet Packages Directory
+packages
+
+# Windows Azure Build Output
+csx
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+[Bb]in
+[Oo]bj
+sql
+TestResults
+[Tt]est[Rr]esult*
+*.Cache
+ClientBin
+[Ss]tyle[Cc]op.*
+~$*
+*.dbmdl
+Generated_Code #added for RIA/Silverlight projects
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML

+ 28 - 0
conf/gitignore/C++

@@ -0,0 +1,28 @@
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app

+ 12 - 0
conf/gitignore/CFWheels

@@ -0,0 +1,12 @@
+# unpacked plugin folders
+plugins/**/*
+
+# files directory where uploads go
+files
+
+# DBMigrate plugin: generated SQL
+db/sql
+
+# AssetBundler plugin: generated bundles
+javascripts/bundles
+stylesheets/bundles

+ 6 - 0
conf/gitignore/CMake

@@ -0,0 +1,6 @@
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Makefile
+cmake_install.cmake
+install_manifest.txt

+ 6 - 0
conf/gitignore/CUDA

@@ -0,0 +1,6 @@
+*.i
+*.ii
+*.gpu
+*.ptx
+*.cubin
+*.fatbin

+ 4 - 0
conf/gitignore/CVS

@@ -0,0 +1,4 @@
+/CVS/*
+*/CVS/*
+.cvsignore
+*/.cvsignore

+ 13 - 0
conf/gitignore/CakePHP

@@ -0,0 +1,13 @@
+# CakePHP 3
+
+/vendor/*
+/config/app.php
+/tmp/*
+/logs/*
+
+# CakePHP 2
+
+/app/tmp/*
+/app/Config/core.php
+/app/Config/database.php
+/vendors/*

+ 9 - 0
conf/gitignore/ChefCookbook

@@ -0,0 +1,9 @@
+.vagrant
+/cookbooks
+
+# Bundler
+bin/*
+.bundle/*
+
+.kitchen/
+.kitchen.local.yml

+ 3 - 0
conf/gitignore/Cloud9

@@ -0,0 +1,3 @@
+# Cloud9 IDE - http://c9.io
+.c9revisions
+.c9

+ 6 - 0
conf/gitignore/CodeIgniter

@@ -0,0 +1,6 @@
+*/config/development
+*/logs/log-*.php
+!*/logs/index.html
+*/cache/*
+!*/cache/index.html
+!*/cache/.htaccess

+ 3 - 0
conf/gitignore/CodeKit

@@ -0,0 +1,3 @@
+# General CodeKit files to ignore
+config.codekit
+/min

+ 3 - 0
conf/gitignore/CommonLisp

@@ -0,0 +1,3 @@
+*.FASL
+*.fasl
+*.lisp-temp

+ 6 - 0
conf/gitignore/Composer

@@ -0,0 +1,6 @@
+composer.phar
+vendor/
+
+# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
+# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
+# composer.lock

+ 3 - 0
conf/gitignore/Concrete5

@@ -0,0 +1,3 @@
+config/site.php
+files/cache/*
+files/tmp/*

+ 3 - 0
conf/gitignore/Coq

@@ -0,0 +1,3 @@
+*.vo
+*.glob
+*.v.d

+ 3 - 0
conf/gitignore/CraftCMS

@@ -0,0 +1,3 @@
+# Craft Storage (cache) [http://buildwithcraft.com/help/craft-storage-gitignore]
+/craft/storage/*
+!/craft/storage/logo/*

+ 5 - 0
conf/gitignore/DM

@@ -0,0 +1,5 @@
+*.dmb
+*.rsc
+*.int
+*.lk
+*.zip

+ 15 - 0
conf/gitignore/Dart

@@ -0,0 +1,15 @@
+# Don’t commit the following directories created by pub.
+.buildlog
+.pub/
+build/
+packages
+.packages
+
+# Or the files created by dart2js.
+*.dart.js
+*.js_
+*.js.deps
+*.js.map
+
+# Include when developing application packages.
+pubspec.lock

+ 2 - 0
conf/gitignore/DartEditor

@@ -0,0 +1,2 @@
+.project
+.buildlog

+ 57 - 0
conf/gitignore/Delphi

@@ -0,0 +1,57 @@
+# Uncomment these types if you want even more clean repository. But be careful.
+# It can make harm to an existing project source. Read explanations below.
+#
+# Resource files are binaries containing manifest, project icon and version info.
+# They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files.
+#*.res
+#
+# Type library file (binary). In old Delphi versions it should be stored.
+# Since Delphi 2009 it is produced from .ridl file and can safely be ignored.
+#*.tlb
+#
+# Diagram Portfolio file. Used by the diagram editor up to Delphi 7.
+# Uncomment this if you are not using diagrams or use newer Delphi version.
+#*.ddp
+#
+# Visual LiveBindings file. Added in Delphi XE2.
+# Uncomment this if you are not using LiveBindings Designer.
+#*.vlb
+#
+# Deployment Manager configuration file for your project. Added in Delphi XE2.
+# Uncomment this if it is not mobile development and you do not use remote debug feature.
+#*.deployproj
+#
+
+# Delphi compiler-generated binaries (safe to delete)
+*.exe
+*.dll
+*.bpl
+*.bpi
+*.dcp
+*.so
+*.apk
+*.drc
+*.map
+*.dres
+*.rsm
+*.tds
+*.dcu
+*.lib
+
+# Delphi autogenerated files (duplicated info)
+*.cfg
+*Resource.rc
+
+# Delphi local files (user-specific info)
+*.local
+*.identcache
+*.projdata
+*.tvsconfig
+*.dsk
+
+# Delphi history and backups
+__history/
+*.~*
+
+# Castalia statistics file
+*.stat

+ 3 - 0
conf/gitignore/Dreamweaver

@@ -0,0 +1,3 @@
+# DW Dreamweaver added files
+_notes
+dwsync.xml

+ 36 - 0
conf/gitignore/Drupal

@@ -0,0 +1,36 @@
+# Ignore configuration files that may contain sensitive information.
+sites/*/*settings*.php
+
+# Ignore paths that contain generated content.
+files/
+sites/*/files
+sites/*/private
+
+# Ignore default text files
+robots.txt
+/CHANGELOG.txt
+/COPYRIGHT.txt
+/INSTALL*.txt
+/LICENSE.txt
+/MAINTAINERS.txt
+/UPGRADE.txt
+/README.txt
+sites/all/README.txt
+sites/all/modules/README.txt
+sites/all/themes/README.txt
+
+# Ignore everything but the "sites" folder ( for non core developer )
+.htaccess
+web.config
+authorize.php
+cron.php
+index.php
+install.php
+update.php
+xmlrpc.php
+/includes
+/misc
+/modules
+/profiles
+/scripts
+/themes

+ 4 - 0
conf/gitignore/EPiServer

@@ -0,0 +1,4 @@
+######################
+## EPiServer Files
+######################
+*License.config

+ 36 - 0
conf/gitignore/Eagle

@@ -0,0 +1,36 @@
+# Ignore list for Eagle, a PCB layout tool
+
+# Backup files
+*.s#?
+*.b#?
+*.l#?
+
+# Eagle project file
+# It contains a serial number and references to the file structure
+# on your computer.
+# comment the following line if you want to have your project file included.
+eagle.epf
+
+# CAM files
+*.$$$
+*.cmp
+*.ly2
+*.l15
+*.sol
+*.plc
+*.stc
+*.sts
+*.crc
+*.crs
+
+*.dri
+*.drl
+*.gpi
+*.pls
+
+*.drd
+*.drd.*
+
+*.info
+
+*.eps

+ 39 - 0
conf/gitignore/Eclipse

@@ -0,0 +1,39 @@
+*.pydevproject
+.metadata
+.gradle
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+
+# Eclipse Core
+.project
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# JDT-specific (Eclipse Java Development Tools)
+.classpath
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# TeXlipse plugin
+.texlipse

+ 2 - 0
conf/gitignore/EiffelStudio

@@ -0,0 +1,2 @@
+# The compilation directoy
+EIFGENs

+ 5 - 0
conf/gitignore/Elisp

@@ -0,0 +1,5 @@
+# Compiled
+*.elc
+
+# Packaging
+.cask

+ 4 - 0
conf/gitignore/Elixir

@@ -0,0 +1,4 @@
+/_build
+/deps
+erl_crash.dump
+*.ez

+ 32 - 0
conf/gitignore/Emacs

@@ -0,0 +1,32 @@
+# -*- mode: gitignore; -*-
+*~
+\#*\#
+/.emacs.desktop
+/.emacs.desktop.lock
+*.elc
+auto-save-list
+tramp
+.\#*
+
+# Org-mode
+.org-id-locations
+*_archive
+
+# flymake-mode
+*_flymake.*
+
+# eshell files
+/eshell/history
+/eshell/lastdir
+
+# elpa packages
+/elpa/
+
+# reftex files
+*.rel
+
+# AUCTeX auto folder
+/auto/
+
+# cask packages
+.cask/

+ 4 - 0
conf/gitignore/Ensime

@@ -0,0 +1,4 @@
+# Ensime specific
+.ensime
+.ensime_cache/
+.ensime_lucene/

+ 10 - 0
conf/gitignore/Erlang

@@ -0,0 +1,10 @@
+.eunit
+deps
+*.o
+*.beam
+*.plt
+erl_crash.dump
+ebin
+rel/example_project
+.concrete/DEV_MODE
+.rebar

+ 1 - 0
conf/gitignore/Espresso

@@ -0,0 +1 @@
+*.esproj

+ 19 - 0
conf/gitignore/ExpressionEngine

@@ -0,0 +1,19 @@
+.DS_Store
+
+# Images
+images/avatars/
+images/captchas/
+images/smileys/
+images/member_photos/
+images/signature_attachments/
+images/pm_attachments/
+
+# For security do not publish the following files
+system/expressionengine/config/database.php
+system/expressionengine/config/config.php
+
+# Caches
+sized/
+thumbs/
+_thumbs/
+*/expressionengine/cache/*

+ 4 - 0
conf/gitignore/ExtJs

@@ -0,0 +1,4 @@
+.architect
+bootstrap.json
+build/
+ext/

+ 2 - 0
conf/gitignore/Fancy

@@ -0,0 +1,2 @@
+*.rbc
+*.fyc

+ 13 - 0
conf/gitignore/Finale

@@ -0,0 +1,13 @@
+*.bak
+*.db
+*.avi
+*.pdf
+*.ps
+*.mid
+*.midi
+*.mp3
+*.aif
+*.wav
+# Some versions of Finale have a bug and randomly save extra copies of
+# the music source as "<Filename> copy.mus"
+*copy.mus

+ 3 - 0
conf/gitignore/FlexBuilder

@@ -0,0 +1,3 @@
+bin/
+bin-debug/
+bin-release/

+ 4 - 0
conf/gitignore/ForceDotCom

@@ -0,0 +1,4 @@
+.project
+.settings
+salesforce.schema
+Referenced Packages

+ 2 - 0
conf/gitignore/FuelPHP

@@ -0,0 +1,2 @@
+fuel/app/logs/*/*/*
+fuel/app/cache/*/*

+ 28 - 0
conf/gitignore/GWT

@@ -0,0 +1,28 @@
+*.class
+
+# Package Files #
+*.jar
+*.war
+
+# gwt caches and compiled units #
+war/gwt_bree/
+gwt-unitCache/
+
+# boilerplate generated classes #
+.apt_generated/
+
+# more caches and things from deploy #
+war/WEB-INF/deploy/
+war/WEB-INF/classes/
+
+#compilation logs
+.gwt/
+
+#caching for already compiled files
+gwt-unitCache/
+
+#gwt junit compilation files
+www-test/
+
+#old GWT (1.5) created this dir
+.gwt-tmp/

+ 5 - 0
conf/gitignore/Gcov

@@ -0,0 +1,5 @@
+# gcc coverage testing tool files
+
+*.gcno
+*.gcda
+*.gcov

+ 16 - 0
conf/gitignore/GitBook

@@ -0,0 +1,16 @@
+# Node rules:
+## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+## Dependency directory
+## Commenting this out is preferred by some people, see
+## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git
+node_modules
+
+# Book build output
+_book
+
+# eBook build output
+*.epub
+*.mobi
+*.pdf

+ 24 - 0
conf/gitignore/Go

@@ -0,0 +1,24 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof

+ 8 - 0
conf/gitignore/Gradle

@@ -0,0 +1,8 @@
+.gradle
+build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar

+ 33 - 0
conf/gitignore/Grails

@@ -0,0 +1,33 @@
+# .gitignore for Grails 1.2 and 1.3
+# Although this should work for most versions of grails, it is
+# suggested that you use the "grails integrate-with --git" command
+# to generate your .gitignore file.
+
+# web application files
+/web-app/WEB-INF/classes
+
+# default HSQL database files for production mode
+/prodDb.*
+
+# general HSQL database files
+*Db.properties
+*Db.script
+
+# logs
+/stacktrace.log
+/test/reports
+/logs
+
+# project release file
+/*.war
+
+# plugin release files
+/*.zip
+/plugin.xml
+
+# older plugin install locations
+/plugins
+/web-app/plugins
+
+# "temporary" build files
+/target

+ 16 - 0
conf/gitignore/Haskell

@@ -0,0 +1,16 @@
+dist
+cabal-dev
+*.o
+*.hi
+*.chi
+*.chs.h
+*.dyn_o
+*.dyn_hi
+.hpc
+.hsenv
+.cabal-sandbox/
+cabal.sandbox.config
+*.prof
+*.aux
+*.hp
+.stack-work/

+ 5 - 0
conf/gitignore/IGORPro

@@ -0,0 +1,5 @@
+# Avoid including Experiment files: they can be created and edited locally to test the ipf files
+*.pxp
+*.pxt
+*.uxp
+*.uxt

+ 2 - 0
conf/gitignore/IPythonNotebook

@@ -0,0 +1,2 @@
+# Temporary data
+.ipynb_checkpoints/

+ 2 - 0
conf/gitignore/Idris

@@ -0,0 +1,2 @@
+*.ibc
+*.o

+ 13 - 0
conf/gitignore/JDeveloper

@@ -0,0 +1,13 @@
+# default application storage directory used by the IDE Performance Cache feature
+.data/
+
+# used for ADF styles caching
+temp/
+
+# default output directories
+classes/
+deploy/
+javadoc/
+
+# lock file, a part of Oracle Credential Store Framework
+cwallet.sso.lck

+ 12 - 0
conf/gitignore/Java

@@ -0,0 +1,12 @@
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*

+ 19 - 0
conf/gitignore/Jboss

@@ -0,0 +1,19 @@
+jboss/server/all/deploy/project.ext
+jboss/server/default/deploy/project.ext
+jboss/server/minimal/deploy/project.ext
+jboss/server/all/log/*.log
+jboss/server/all/tmp/**/*
+jboss/server/all/data/**/*
+jboss/server/all/work/**/*
+jboss/server/default/log/*.log
+jboss/server/default/tmp/**/*
+jboss/server/default/data/**/*
+jboss/server/default/work/**/*
+jboss/server/minimal/log/*.log
+jboss/server/minimal/tmp/**/*
+jboss/server/minimal/data/**/*
+jboss/server/minimal/work/**/*
+
+# deployed package files #
+
+*.DEPLOYED

+ 3 - 0
conf/gitignore/Jekyll

@@ -0,0 +1,3 @@
+_site/
+.sass-cache/
+.jekyll-metadata

+ 46 - 0
conf/gitignore/JetBrains

@@ -0,0 +1,46 @@
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
+
+*.iml
+
+## Directory-based project format:
+.idea/
+# if you remove the above rule, at least ignore the following:
+
+# User-specific stuff:
+# .idea/workspace.xml
+# .idea/tasks.xml
+# .idea/dictionaries
+
+# Sensitive or high-churn files:
+# .idea/dataSources.ids
+# .idea/dataSources.xml
+# .idea/sqlDataSources.xml
+# .idea/dynamic.xml
+# .idea/uiDesigner.xml
+
+# Gradle:
+# .idea/gradle.xml
+# .idea/libraries
+
+# Mongo Explorer plugin:
+# .idea/mongoSettings.xml
+
+## File-based project format:
+*.ipr
+*.iws
+
+## Plugin-specific files:
+
+# IntelliJ
+/out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties

+ 525 - 0
conf/gitignore/Joomla

@@ -0,0 +1,525 @@
+/.gitignore
+/.htaccess
+/administrator/cache/*
+/administrator/components/com_admin/*
+/administrator/components/com_ajax/*
+/administrator/components/com_tags/*
+/administrator/components/com_banners/*
+/administrator/components/com_cache/*
+/administrator/components/com_postinstall/*
+/administrator/components/com_joomlaupdate/*
+/administrator/components/com_contenthistory/*
+/administrator/components/com_categories/*
+/administrator/components/com_checkin/*
+/administrator/components/com_config/*
+/administrator/components/com_contact/*
+/administrator/components/com_content/*
+/administrator/components/com_cpanel/*
+/administrator/components/com_finder/*
+/administrator/components/com_installer/*
+/administrator/components/com_languages/*
+/administrator/components/com_login/*
+/administrator/components/com_media/*
+/administrator/components/com_menus/*
+/administrator/components/com_messages/*
+/administrator/components/com_modules/*
+/administrator/components/com_newsfeeds/*
+/administrator/components/com_plugins/*
+/administrator/components/com_redirect/*
+/administrator/components/com_search/*
+/administrator/components/com_templates/*
+/administrator/components/com_users/*
+/administrator/components/com_weblinks/*
+/administrator/components/index.html
+/administrator/help/*
+/administrator/includes/*
+/administrator/language/en-GB/en-GB.com_ajax.ini
+/administrator/language/en-GB/en-GB.com_ajax.sys.ini
+/administrator/language/en-GB/en-GB.com_contenthistory.ini
+/administrator/language/en-GB/en-GB.com_contenthistory.sys.ini
+/administrator/language/en-GB/en-GB.com_joomlaupdate.ini
+/administrator/language/en-GB/en-GB.com_joomlaupdate.sys.ini
+/administrator/language/en-GB/en-GB.com_postinstall.ini
+/administrator/language/en-GB/en-GB.com_postinstall.sys.ini
+/administrator/language/en-GB/en-GB.com_sitemapjen.sys.ini
+/administrator/language/en-GB/en-GB.com_tags.ini
+/administrator/language/en-GB/en-GB.com_tags.sys.ini
+/administrator/language/en-GB/en-GB.mod_stats_admin.ini
+/administrator/language/en-GB/en-GB.mod_stats_admin.sys.ini
+/administrator/language/en-GB/en-GB.plg_authentication_cookie.ini
+/administrator/language/en-GB/en-GB.plg_authentication_cookie.sys.ini
+/administrator/language/en-GB/en-GB.plg_content_contact.ini
+/administrator/language/en-GB/en-GB.plg_content_contact.sys.ini
+/administrator/language/en-GB/en-GB.plg_content_finder.ini
+/administrator/language/en-GB/en-GB.plg_content_finder.sys.ini
+/administrator/language/en-GB/en-GB.plg_finder_categories.ini
+/administrator/language/en-GB/en-GB.plg_finder_categories.sys.ini
+/administrator/language/en-GB/en-GB.plg_finder_contacts.ini
+/administrator/language/en-GB/en-GB.plg_finder_contacts.sys.ini
+/administrator/language/en-GB/en-GB.plg_finder_content.ini
+/administrator/language/en-GB/en-GB.plg_finder_content.sys.ini
+/administrator/language/en-GB/en-GB.plg_finder_newsfeeds.sys.ini
+/administrator/language/en-GB/en-GB.plg_finder_newsfeeds.ini
+/administrator/language/en-GB/en-GB.plg_finder_tags.ini
+/administrator/language/en-GB/en-GB.plg_finder_tags.sys.ini
+/administrator/language/en-GB/en-GB.plg_finder_weblinks.ini
+/administrator/language/en-GB/en-GB.plg_finder_weblinks.sys.ini
+/administrator/language/en-GB/en-GB.plg_installer_webinstaller.ini
+/administrator/language/en-GB/en-GB.plg_installer_webinstaller.sys.ini
+/administrator/language/en-GB/en-GB.plg_quickicon_joomlaupdate.ini
+/administrator/language/en-GB/en-GB.plg_quickicon_joomlaupdate.sys.ini
+/administrator/language/en-GB/en-GB.plg_search_tags.ini
+/administrator/language/en-GB/en-GB.plg_search_tags.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_languagecode.ini
+/administrator/language/en-GB/en-GB.plg_system_languagecode.sys.ini
+/administrator/language/en-GB/en-GB.plg_twofactorauth_totp.ini
+/administrator/language/en-GB/en-GB.plg_twofactorauth_totp.sys.ini
+/administrator/language/en-GB/en-GB.plg_twofactorauth_yubikey.ini
+/administrator/language/en-GB/en-GB.plg_twofactorauth_yubikey.sys.ini
+/administrator/language/en-GB/en-GB.tpl_isis.ini
+/administrator/language/en-GB/en-GB.tpl_isis.sys.ini
+/administrator/language/en-GB/install.xml
+/administrator/language/en-GB/en-GB.com_admin.ini
+/administrator/language/en-GB/en-GB.com_admin.sys.ini
+/administrator/language/en-GB/en-GB.com_banners.ini
+/administrator/language/en-GB/en-GB.com_banners.sys.ini
+/administrator/language/en-GB/en-GB.com_cache.ini
+/administrator/language/en-GB/en-GB.com_cache.sys.ini
+/administrator/language/en-GB/en-GB.com_categories.ini
+/administrator/language/en-GB/en-GB.com_categories.sys.ini
+/administrator/language/en-GB/en-GB.com_checkin.ini
+/administrator/language/en-GB/en-GB.com_checkin.sys.ini
+/administrator/language/en-GB/en-GB.com_config.ini
+/administrator/language/en-GB/en-GB.com_config.sys.ini
+/administrator/language/en-GB/en-GB.com_contact.ini
+/administrator/language/en-GB/en-GB.com_contact.sys.ini
+/administrator/language/en-GB/en-GB.com_content.ini
+/administrator/language/en-GB/en-GB.com_content.sys.ini
+/administrator/language/en-GB/en-GB.com_cpanel.ini
+/administrator/language/en-GB/en-GB.com_cpanel.sys.ini
+/administrator/language/en-GB/en-GB.com_finder.ini
+/administrator/language/en-GB/en-GB.com_finder.sys.ini
+/administrator/language/en-GB/en-GB.com_installer.ini
+/administrator/language/en-GB/en-GB.com_installer.sys.ini
+/administrator/language/en-GB/en-GB.com_languages.ini
+/administrator/language/en-GB/en-GB.com_languages.sys.ini
+/administrator/language/en-GB/en-GB.com_login.ini
+/administrator/language/en-GB/en-GB.com_login.sys.ini
+/administrator/language/en-GB/en-GB.com_mailto.sys.ini
+/administrator/language/en-GB/en-GB.com_media.ini
+/administrator/language/en-GB/en-GB.com_media.sys.ini
+/administrator/language/en-GB/en-GB.com_menus.ini
+/administrator/language/en-GB/en-GB.com_menus.sys.ini
+/administrator/language/en-GB/en-GB.com_messages.ini
+/administrator/language/en-GB/en-GB.com_messages.sys.ini
+/administrator/language/en-GB/en-GB.com_modules.ini
+/administrator/language/en-GB/en-GB.com_modules.sys.ini
+/administrator/language/en-GB/en-GB.com_newsfeeds.ini
+/administrator/language/en-GB/en-GB.com_newsfeeds.sys.ini
+/administrator/language/en-GB/en-GB.com_plugins.ini
+/administrator/language/en-GB/en-GB.com_plugins.sys.ini
+/administrator/language/en-GB/en-GB.com_redirect.ini
+/administrator/language/en-GB/en-GB.com_redirect.sys.ini
+/administrator/language/en-GB/en-GB.com_search.ini
+/administrator/language/en-GB/en-GB.com_search.sys.ini
+/administrator/language/en-GB/en-GB.com_templates.ini
+/administrator/language/en-GB/en-GB.com_templates.sys.ini
+/administrator/language/en-GB/en-GB.com_users.ini
+/administrator/language/en-GB/en-GB.com_users.sys.ini
+/administrator/language/en-GB/en-GB.com_weblinks.ini
+/administrator/language/en-GB/en-GB.com_weblinks.sys.ini
+/administrator/language/en-GB/en-GB.com_wrapper.ini
+/administrator/language/en-GB/en-GB.com_wrapper.sys.ini
+/administrator/language/en-GB/en-GB.ini
+/administrator/language/en-GB/en-GB.lib_joomla.ini
+/administrator/language/en-GB/en-GB.localise.php
+/administrator/language/en-GB/en-GB.mod_custom.ini
+/administrator/language/en-GB/en-GB.mod_custom.sys.ini
+/administrator/language/en-GB/en-GB.mod_feed.ini
+/administrator/language/en-GB/en-GB.mod_feed.sys.ini
+/administrator/language/en-GB/en-GB.mod_latest.ini
+/administrator/language/en-GB/en-GB.mod_latest.sys.ini
+/administrator/language/en-GB/en-GB.mod_logged.ini
+/administrator/language/en-GB/en-GB.mod_logged.sys.ini
+/administrator/language/en-GB/en-GB.mod_login.ini
+/administrator/language/en-GB/en-GB.mod_login.sys.ini
+/administrator/language/en-GB/en-GB.mod_menu.ini
+/administrator/language/en-GB/en-GB.mod_menu.sys.ini
+/administrator/language/en-GB/en-GB.mod_multilangstatus.ini
+/administrator/language/en-GB/en-GB.mod_multilangstatus.sys.ini
+/administrator/language/en-GB/en-GB.mod_online.ini
+/administrator/language/en-GB/en-GB.mod_online.sys.ini
+/administrator/language/en-GB/en-GB.mod_popular.ini
+/administrator/language/en-GB/en-GB.mod_popular.sys.ini
+/administrator/language/en-GB/en-GB.mod_quickicon.ini
+/administrator/language/en-GB/en-GB.mod_quickicon.sys.ini
+/administrator/language/en-GB/en-GB.mod_status.ini
+/administrator/language/en-GB/en-GB.mod_status.sys.ini
+/administrator/language/en-GB/en-GB.mod_submenu.ini
+/administrator/language/en-GB/en-GB.mod_submenu.sys.ini
+/administrator/language/en-GB/en-GB.mod_title.ini
+/administrator/language/en-GB/en-GB.mod_title.sys.ini
+/administrator/language/en-GB/en-GB.mod_toolbar.ini
+/administrator/language/en-GB/en-GB.mod_toolbar.sys.ini
+/administrator/language/en-GB/en-GB.mod_unread.ini
+/administrator/language/en-GB/en-GB.mod_unread.sys.ini
+/administrator/language/en-GB/en-GB.mod_version.ini
+/administrator/language/en-GB/en-GB.mod_version.sys.ini
+/administrator/language/en-GB/en-GB.plg_authentication_example.ini
+/administrator/language/en-GB/en-GB.plg_authentication_example.sys.ini
+/administrator/language/en-GB/en-GB.plg_authentication_gmail.ini
+/administrator/language/en-GB/en-GB.plg_authentication_gmail.sys.ini
+/administrator/language/en-GB/en-GB.plg_authentication_joomla.ini
+/administrator/language/en-GB/en-GB.plg_authentication_joomla.sys.ini
+/administrator/language/en-GB/en-GB.plg_authentication_ldap.ini
+/administrator/language/en-GB/en-GB.plg_authentication_ldap.sys.ini
+/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.ini
+/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.sys.ini
+/administrator/language/en-GB/en-GB.plg_content_emailcloak.ini
+/administrator/language/en-GB/en-GB.plg_content_emailcloak.sys.ini
+/administrator/language/en-GB/en-GB.plg_content_geshi.ini
+/administrator/language/en-GB/en-GB.plg_content_geshi.sys.ini
+/administrator/language/en-GB/en-GB.plg_content_joomla.ini
+/administrator/language/en-GB/en-GB.plg_content_joomla.sys.ini
+/administrator/language/en-GB/en-GB.plg_content_loadmodule.ini
+/administrator/language/en-GB/en-GB.plg_content_loadmodule.sys.ini
+/administrator/language/en-GB/en-GB.plg_content_pagebreak.ini
+/administrator/language/en-GB/en-GB.plg_content_pagebreak.sys.ini
+/administrator/language/en-GB/en-GB.plg_content_pagenavigation.ini
+/administrator/language/en-GB/en-GB.plg_content_pagenavigation.sys.ini
+/administrator/language/en-GB/en-GB.plg_content_vote.ini
+/administrator/language/en-GB/en-GB.plg_content_vote.sys.ini
+/administrator/language/en-GB/en-GB.plg_editors_codemirror.ini
+/administrator/language/en-GB/en-GB.plg_editors_codemirror.sys.ini
+/administrator/language/en-GB/en-GB.plg_editors_none.ini
+/administrator/language/en-GB/en-GB.plg_editors_none.sys.ini
+/administrator/language/en-GB/en-GB.plg_editors_tinymce.ini
+/administrator/language/en-GB/en-GB.plg_editors_tinymce.sys.ini
+/administrator/language/en-GB/en-GB.plg_editors-xtd_article.ini
+/administrator/language/en-GB/en-GB.plg_editors-xtd_article.sys.ini
+/administrator/language/en-GB/en-GB.plg_editors-xtd_image.ini
+/administrator/language/en-GB/en-GB.plg_editors-xtd_image.sys.ini
+/administrator/language/en-GB/en-GB.plg_editors-xtd_pagebreak.ini
+/administrator/language/en-GB/en-GB.plg_editors-xtd_pagebreak.sys.ini
+/administrator/language/en-GB/en-GB.plg_editors-xtd_readmore.ini
+/administrator/language/en-GB/en-GB.plg_editors-xtd_readmore.sys.ini
+/administrator/language/en-GB/en-GB.plg_extension_joomla.ini
+/administrator/language/en-GB/en-GB.plg_extension_joomla.sys.ini
+/administrator/language/en-GB/en-GB.plg_quickicon_extensionupdate.ini
+/administrator/language/en-GB/en-GB.plg_quickicon_extensionupdate.sys.ini
+/administrator/language/en-GB/en-GB.plg_search_categories.ini
+/administrator/language/en-GB/en-GB.plg_search_categories.sys.ini
+/administrator/language/en-GB/en-GB.plg_search_contacts.ini
+/administrator/language/en-GB/en-GB.plg_search_contacts.sys.ini
+/administrator/language/en-GB/en-GB.plg_search_content.ini
+/administrator/language/en-GB/en-GB.plg_search_content.sys.ini
+/administrator/language/en-GB/en-GB.plg_search_newsfeeds.ini
+/administrator/language/en-GB/en-GB.plg_search_newsfeeds.sys.ini
+/administrator/language/en-GB/en-GB.plg_search_weblinks.ini
+/administrator/language/en-GB/en-GB.plg_search_weblinks.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_cache.ini
+/administrator/language/en-GB/en-GB.plg_system_cache.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_debug.ini
+/administrator/language/en-GB/en-GB.plg_system_debug.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_highlight.ini
+/administrator/language/en-GB/en-GB.plg_system_highlight.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_languagefilter.ini
+/administrator/language/en-GB/en-GB.plg_system_languagefilter.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_log.ini
+/administrator/language/en-GB/en-GB.plg_system_logout.ini
+/administrator/language/en-GB/en-GB.plg_system_logout.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_log.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_p3p.ini
+/administrator/language/en-GB/en-GB.plg_system_p3p.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_redirect.ini
+/administrator/language/en-GB/en-GB.plg_system_redirect.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_remember.ini
+/administrator/language/en-GB/en-GB.plg_system_remember.sys.ini
+/administrator/language/en-GB/en-GB.plg_system_sef.ini
+/administrator/language/en-GB/en-GB.plg_system_sef.sys.ini
+/administrator/language/en-GB/en-GB.plg_user_contactcreator.ini
+/administrator/language/en-GB/en-GB.plg_user_contactcreator.sys.ini
+/administrator/language/en-GB/en-GB.plg_user_joomla.ini
+/administrator/language/en-GB/en-GB.plg_user_joomla.sys.ini
+/administrator/language/en-GB/en-GB.plg_user_profile.ini
+/administrator/language/en-GB/en-GB.plg_user_profile.sys.ini
+/administrator/language/en-GB/en-GB.tpl_bluestork.ini
+/administrator/language/en-GB/en-GB.tpl_bluestork.sys.ini
+/administrator/language/en-GB/en-GB.tpl_hathor.ini
+/administrator/language/en-GB/en-GB.tpl_hathor.sys.ini
+/administrator/language/en-GB/en-GB.xml
+/administrator/language/en-GB/index.html
+/administrator/language/overrides/*
+/administrator/language/index.html
+/administrator/manifests/*
+/administrator/modules/mod_custom/*
+/administrator/modules/mod_feed/*
+/administrator/modules/mod_latest/*
+/administrator/modules/mod_logged/*
+/administrator/modules/mod_login/*
+/administrator/modules/mod_menu/*
+/administrator/modules/mod_multilangstatus/*
+/administrator/modules/mod_online/*
+/administrator/modules/mod_popular/*
+/administrator/modules/mod_quickicon/*
+/administrator/modules/mod_status/*
+/administrator/modules/mod_submenu/*
+/administrator/modules/mod_title/*
+/administrator/modules/mod_toolbar/*
+/administrator/modules/mod_unread/*
+/administrator/modules/mod_version/*
+/administrator/modules/mod_stats_admin/*
+/administrator/modules/index.html
+/administrator/templates/bluestork/*
+/administrator/templates/isis/*
+/administrator/templates/hathor/*
+/administrator/templates/system/*
+/administrator/templates/index.html
+/administrator/index.php
+/cache/*
+/bin/*
+/cli/*
+/components/com_banners/*
+/components/com_ajax/*
+/components/com_config/*
+/components/com_contenthistory/*
+/components/com_tags/*
+/components/com_contact/*
+/components/com_content/*
+/components/com_finder/*
+/components/com_mailto/*
+/components/com_media/*
+/components/com_newsfeeds/*
+/components/com_search/*
+/components/com_users/*
+/components/com_weblinks/*
+/components/com_wrapper/*
+/components/index.html
+/images/banners/*
+/images/sampledata/*
+/images/joomla*
+/images/index.html
+/images/powered_by.png
+/includes/*
+/installation/*
+/language/en-GB/en-GB.com_ajax.ini
+/language/en-GB/en-GB.com_config.ini
+/language/en-GB/en-GB.com_contact.ini
+/language/en-GB/en-GB.com_finder.ini
+/language/en-GB/en-GB.com_tags.ini
+/language/en-GB/en-GB.finder_cli.ini
+/language/en-GB/en-GB.lib_fof.sys.ini
+/language/en-GB/en-GB.com_content.ini
+/language/en-GB/en-GB.lib_idna_convert.sys.ini
+/language/en-GB/en-GB.com_mailto.ini
+/language/en-GB/en-GB.lib_joomla.sys.ini
+/language/en-GB/en-GB.lib_phpass.sys.ini
+/language/en-GB/en-GB.lib_phpmailer.sys.ini
+/language/en-GB/en-GB.lib_phputf8.sys.ini
+/language/en-GB/en-GB.lib_simplepie.sys.ini
+/language/en-GB/en-GB.com_media.ini
+/language/en-GB/en-GB.mod_finder.ini
+/language/en-GB/en-GB.com_messages.ini
+/language/en-GB/en-GB.mod_tags_popular.ini
+/language/en-GB/en-GB.mod_tags_popular.sys.ini
+/language/en-GB/en-GB.mod_tags_similar.ini
+/language/en-GB/en-GB.mod_tags_similar.sys.ini
+/language/en-GB/en-GB.mod_finder.sys.ini
+/language/en-GB/en-GB.tpl_beez3.ini
+/language/en-GB/en-GB.tpl_beez3.sys.ini
+/language/en-GB/en-GB.com_newsfeeds.ini
+/language/en-GB/en-GB.tpl_protostar.ini
+/language/en-GB/en-GB.tpl_protostar.sys.ini
+/language/en-GB/en-GB.com_search.ini
+/language/en-GB/en-GB.com_users.ini
+/language/en-GB/en-GB.com_weblinks.ini
+/language/en-GB/en-GB.com_wrapper.ini
+/language/en-GB/en-GB.files_joomla.sys.ini
+/language/en-GB/en-GB.ini
+/language/en-GB/en-GB.lib_joomla.ini
+/language/en-GB/en-GB.localise.php
+/language/en-GB/en-GB.mod_articles_archive.ini
+/language/en-GB/en-GB.mod_articles_archive.sys.ini
+/language/en-GB/en-GB.mod_articles_categories.ini
+/language/en-GB/en-GB.mod_articles_categories.sys.ini
+/language/en-GB/en-GB.mod_articles_category.ini
+/language/en-GB/en-GB.mod_articles_category.sys.ini
+/language/en-GB/en-GB.mod_articles_latest.ini
+/language/en-GB/en-GB.mod_articles_latest.sys.ini
+/language/en-GB/en-GB.mod_articles_news.ini
+/language/en-GB/en-GB.mod_articles_news.sys.ini
+/language/en-GB/en-GB.mod_articles_popular.ini
+/language/en-GB/en-GB.mod_articles_popular.sys.ini
+/language/en-GB/en-GB.mod_banners.ini
+/language/en-GB/en-GB.mod_banners.sys.ini
+/language/en-GB/en-GB.mod_breadcrumbs.ini
+/language/en-GB/en-GB.mod_breadcrumbs.sys.ini
+/language/en-GB/en-GB.mod_custom.ini
+/language/en-GB/en-GB.mod_custom.sys.ini
+/language/en-GB/en-GB.mod_feed.ini
+/language/en-GB/en-GB.mod_feed.sys.ini
+/language/en-GB/en-GB.mod_footer.ini
+/language/en-GB/en-GB.mod_footer.sys.ini
+/language/en-GB/en-GB.mod_languages.ini
+/language/en-GB/en-GB.mod_languages.sys.ini
+/language/en-GB/en-GB.mod_login.ini
+/language/en-GB/en-GB.mod_login.sys.ini
+/language/en-GB/en-GB.mod_menu.ini
+/language/en-GB/en-GB.mod_menu.sys.ini
+/language/en-GB/en-GB.mod_random_image.ini
+/language/en-GB/en-GB.mod_random_image.sys.ini
+/language/en-GB/en-GB.mod_related_items.ini
+/language/en-GB/en-GB.mod_related_items.sys.ini
+/language/en-GB/en-GB.mod_search.ini
+/language/en-GB/en-GB.mod_search.sys.ini
+/language/en-GB/en-GB.mod_stats.ini
+/language/en-GB/en-GB.mod_stats.sys.ini
+/language/en-GB/en-GB.mod_syndicate.ini
+/language/en-GB/en-GB.mod_syndicate.sys.ini
+/language/en-GB/en-GB.mod_users_latest.ini
+/language/en-GB/en-GB.mod_users_latest.sys.ini
+/language/en-GB/en-GB.mod_weblinks.ini
+/language/en-GB/en-GB.mod_weblinks.sys.ini
+/language/en-GB/en-GB.mod_whosonline.ini
+/language/en-GB/en-GB.mod_whosonline.sys.ini
+/language/en-GB/en-GB.mod_wrapper.ini
+/language/en-GB/en-GB.mod_wrapper.sys.ini
+/language/en-GB/en-GB.tpl_atomic.ini
+/language/en-GB/en-GB.tpl_atomic.sys.ini
+/language/en-GB/en-GB.tpl_beez_20.ini
+/language/en-GB/en-GB.tpl_beez_20.sys.ini
+/language/en-GB/en-GB.tpl_beez5.ini
+/language/en-GB/en-GB.tpl_beez5.sys.ini
+/language/en-GB/en-GB.xml
+/language/en-GB/index.html
+/language/en-GB/install.xml
+/language/overrides/*
+/language/index.html
+/libraries/cms.php
+/libraries/cms/*
+/libraries/joomla/*
+/libraries/phpmailer/*
+/libraries/phputf8/*
+/libraries/simplepie/*
+/libraries/index.html
+/libraries/import.php
+/libraries/loader.php
+/libraries/platform.php
+/logs/*
+/media/cms/*
+/media/com_finder/*
+/media/contacts/*
+/media/editors/*
+/media/mailto/*
+/media/media/*
+/media/mod_languages/*
+/media/overrider/*
+/media/plg_quickicon_extensionupdate/*
+/media/plg_quickicon_joomlaupdate/*
+/media/plg_system_highlight/*
+/media/system/*
+/media/index.html
+/modules/mod_articles_archive/*
+/modules/mod_articles_categories/*
+/modules/mod_articles_category/*
+/modules/mod_articles_latest/*
+/modules/mod_articles_news/*
+/modules/mod_articles_popular/*
+/modules/mod_banners/*
+/modules/mod_breadcrumbs/*
+/modules/mod_custom/*
+/modules/mod_feed/*
+/modules/mod_finder/*
+/modules/mod_footer/*
+/modules/mod_languages/*
+/modules/mod_login/*
+/modules/mod_menu/*
+/modules/mod_random_image/*
+/modules/mod_related_items/*
+/modules/mod_search/*
+/modules/mod_stats/*
+/modules/mod_syndicate/*
+/modules/mod_users_latest/*
+/modules/mod_weblinks/*
+/modules/mod_whosonline/*
+/modules/mod_wrapper/*
+/modules/index.html
+/plugins/authentication/example/*
+/plugins/authentication/gmail/*
+/plugins/authentication/joomla/*
+/plugins/authentication/ldap/*
+/plugins/authentication/index.html
+/plugins/captcha/recaptcha/*
+/plugins/captcha/index.html
+/plugins/content/emailcloak/*
+/plugins/content/example/*
+/plugins/content/finder/*
+/plugins/content/geshi/*
+/plugins/content/joomla/*
+/plugins/content/loadmodule/*
+/plugins/content/pagebreak/*
+/plugins/content/pagenavigation/*
+/plugins/content/vote/*
+/plugins/content/contact/*
+/plugins/content/index.html
+/plugins/editors/codemirror/*
+/plugins/editors/none/*
+/plugins/editors/tinymce/*
+/plugins/editors/index.html
+/plugins/editors-xtd/article/*
+/plugins/editors-xtd/image/*
+/plugins/editors-xtd/pagebreak/*
+/plugins/editors-xtd/readmore/*
+/plugins/editors-xtd/index.html
+/plugins/extension/example/*
+/plugins/extension/joomla/*
+/plugins/extension/index.html
+/plugins/finder/index.html
+/plugins/finder/categories/*
+/plugins/finder/contacts/*
+/plugins/finder/content/*
+/plugins/finder/newsfeeds/*
+/plugins/finder/tags/*
+/plugins/finder/weblinks/*
+/plugins/installer/*
+/plugins/quickicon/extensionupdate/*
+/plugins/quickicon/joomlaupdate/*
+/plugins/quickicon/index.html
+/plugins/search/categories/*
+/plugins/search/contacts/*
+/plugins/search/content/*
+/plugins/search/newsfeeds/*
+/plugins/search/weblinks/*
+/plugins/search/tags/*
+/plugins/search/index.html
+/plugins/system/cache/*
+/plugins/system/debug/*
+/plugins/system/highlight/*
+/plugins/system/languagecode/*
+/plugins/system/languagefilter/*
+/plugins/system/log/*
+/plugins/system/logout/*
+/plugins/system/p3p/*
+/plugins/system/redirect/*
+/plugins/system/remember/*
+/plugins/system/sef/*
+/plugins/system/index.html
+/plugins/twofactorauth/*
+/plugins/user/contactcreator/*
+/plugins/user/example/*
+/plugins/user/joomla/*
+/plugins/user/profile/*
+/plugins/user/index.html
+/plugins/index.html
+/templates/atomic/*
+/templates/beez3/*
+/templates/beez_20/*
+/templates/beez5/*
+/templates/protostar/*
+/templates/system/*
+/templates/index.html
+/tmp/*
+/configuration.php
+/index.php
+/joomla.xml
+/*.txt

+ 2 - 0
conf/gitignore/KDevelop4

@@ -0,0 +1,2 @@
+*.kdev4
+.kdev4/

+ 3 - 0
conf/gitignore/Kate

@@ -0,0 +1,3 @@
+# Swap Files #
+.*.kate-swp
+.swp.*

+ 13 - 0
conf/gitignore/KiCAD

@@ -0,0 +1,13 @@
+# For PCBs designed using KiCAD: http://www.kicad-pcb.org/
+
+# Temporary files
+*.000
+*.bak
+*.bck
+*.kicad_pcb-bak
+
+# Netlist files (exported from Eeschema)
+*.net
+
+# Autorouter files (exported from Pcbnew)
+.dsn

+ 0 - 0
conf/gitignore/Kohana


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.