mirror of https://github.com/go-gitea/gitea
# Conflicts: # models/issue_comment.go # models/migrations/migrations.go # models/migrations/v64.go # models/models.go # public/css/index.csspull/3748/head
commit
6d00c1a7ce
@ -0,0 +1,611 @@ |
||||
--- |
||||
date: "2018-05-07T13:00:00+02:00" |
||||
title: "Gitea compared to other Git hosting options" |
||||
slug: "comparison" |
||||
weight: 5 |
||||
toc: true |
||||
draft: false |
||||
menu: |
||||
sidebar: |
||||
parent: "features" |
||||
name: "Comparison" |
||||
weight: 5 |
||||
identifier: "comparison" |
||||
--- |
||||
|
||||
# Gitea compared to other Git hosting options |
||||
|
||||
To help decide if Gitea is suited for your needs here is how it compares to other Git self hosted options. |
||||
|
||||
Be warned that we don't regularly check for feature changes in other products so this list can be outdated. If you find anything that needs to be updated in table below please report [issue on Github](https://github.com/go-gitea/gitea/issues). |
||||
|
||||
_Symbols used in table:_ |
||||
|
||||
* _✓ - supported_ |
||||
|
||||
* _⁄ - supported with limited functionality_ |
||||
|
||||
* _✘ - unsupported_ |
||||
|
||||
<table border="1" cellpadding="4"> |
||||
<thead> |
||||
<tr> |
||||
<td>Feature</td> |
||||
<td>Gitea</td> |
||||
<td>Gogs</td> |
||||
<td>GitHub EE</td> |
||||
<td>GitLab CE</td> |
||||
<td>GitLab EE</td> |
||||
<td>BitBucket</td> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr> |
||||
<td>Open source and free</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Issue tracker</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Pull/Merge requests</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Squash merging</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Rebase merging</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>⁄</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Pull/Merge request inline comments</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Pull/Merge request approval</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>⁄</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Merge conflict resolution</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Restrict push and merge access to certain users</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>⁄</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Markdown support</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Issues and pull/merge requests templates</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Revert specific commits or a merge request</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Labels</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Time tracking</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Multiple assignees for issues</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Related issues</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>⁄</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Confidential issues</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Comment reactions</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Lock Discussion</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Batch issue handling</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Issue Boards</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Create new branches from issues</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Commit graph</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Web code editor</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Branch manager</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Create new branches</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Repository topics</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Repository code search</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Global code search</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Issue search</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Global issue search</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Git LFS 2.0</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>⁄</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Integrated Git-powered wiki</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Static Git-powered pages</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Group Milestones</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Granular user roles (Code, Issues, Wiki etc)</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Cherry-picking changes</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>GPG Signed Commits</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Reject unsigned commits</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Verified Committer</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>?</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Subgroups: groups within groups</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Custom Git Hooks</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Repository Activity page</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Deploy Tokens</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Repository Tokens with write rights</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Easy upgrade process</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Built-in Container Registry</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>External git mirroring</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>AD / LDAP integration</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Multiple LDAP / AD server support</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>LDAP user synchronization</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>OpenId Connect support</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>?</td> |
||||
</tr> |
||||
<tr> |
||||
<td>OAuth 2.0 integration (external authorization)</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>⁄</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>?</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Act as OAuth 2.0 provider</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Two factor authentication (2FA)</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Webhook support</td> |
||||
<td>⁄</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Mattermost/Slack integration</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>⁄</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>⁄</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Discord integration</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Built-in CI/CD</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>External CI/CD status display</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Multiple database support</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>⁄</td> |
||||
<td>⁄</td> |
||||
<td>✓</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Multiple OS support</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
<tr> |
||||
<td>Low resource usage (RAM/CPU)</td> |
||||
<td>✓</td> |
||||
<td>✓</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
<td>✘</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
@ -0,0 +1,41 @@ |
||||
--- |
||||
date: "2018-05-10T16:00:00+02:00" |
||||
title: "Usage: Issue and Pull Request templates" |
||||
slug: "issue-pull-request-templates" |
||||
weight: 15 |
||||
toc: true |
||||
draft: false |
||||
menu: |
||||
sidebar: |
||||
parent: "usage" |
||||
name: "Issue and Pull Request templates" |
||||
weight: 15 |
||||
identifier: "issue-pull-request-templates" |
||||
--- |
||||
|
||||
# Issue and Pull Request Templates |
||||
|
||||
For some projects there are a standard list of questions that users need to be asked |
||||
for creating an issue, or adding a pull request. Gitea supports adding templates to the |
||||
main branch of the repository so that they can autopopulate the form when users are |
||||
creating issues, and pull requests. This will cut down on the initial back and forth |
||||
of getting some clarifiying details. |
||||
|
||||
Possible file names for issue templates: |
||||
|
||||
* ISSUE_TEMPLATE.md |
||||
* issue_template.md |
||||
* .gitea/ISSUE_TEMPLATE.md |
||||
* .gitea/issue_template.md |
||||
* .github/ISSUE_TEMPLATE.md |
||||
* .github/issue_template.md |
||||
|
||||
|
||||
Possible file names for PR templates: |
||||
|
||||
* PULL_REQUEST_TEMPLATE.md |
||||
* pull_request_template.md |
||||
* .gitea/PULL_REQUEST_TEMPLATE.md |
||||
* .gitea/pull_request_template.md |
||||
* .github/PULL_REQUEST_TEMPLATE.md |
||||
* .github/pull_request_template.md |
@ -0,0 +1,194 @@ |
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations |
||||
|
||||
import ( |
||||
"net/http" |
||||
"os" |
||||
"strings" |
||||
"testing" |
||||
|
||||
"code.gitea.io/gitea/models" |
||||
|
||||
"github.com/Unknwon/i18n" |
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
type ldapUser struct { |
||||
UserName string |
||||
Password string |
||||
FullName string |
||||
Email string |
||||
OtherEmails []string |
||||
IsAdmin bool |
||||
SSHKeys []string |
||||
} |
||||
|
||||
var gitLDAPUsers = []ldapUser{ |
||||
{ |
||||
UserName: "professor", |
||||
Password: "professor", |
||||
FullName: "Hubert Farnsworth", |
||||
Email: "professor@planetexpress.com", |
||||
OtherEmails: []string{"hubert@planetexpress.com"}, |
||||
IsAdmin: true, |
||||
}, |
||||
{ |
||||
UserName: "hermes", |
||||
Password: "hermes", |
||||
FullName: "Conrad Hermes", |
||||
Email: "hermes@planetexpress.com", |
||||
IsAdmin: true, |
||||
}, |
||||
{ |
||||
UserName: "fry", |
||||
Password: "fry", |
||||
FullName: "Philip Fry", |
||||
Email: "fry@planetexpress.com", |
||||
}, |
||||
{ |
||||
UserName: "leela", |
||||
Password: "leela", |
||||
FullName: "Leela Turanga", |
||||
Email: "leela@planetexpress.com", |
||||
}, |
||||
{ |
||||
UserName: "bender", |
||||
Password: "bender", |
||||
FullName: "Bender Rodríguez", |
||||
Email: "bender@planetexpress.com", |
||||
}, |
||||
} |
||||
|
||||
var otherLDAPUsers = []ldapUser{ |
||||
{ |
||||
UserName: "zoidberg", |
||||
Password: "zoidberg", |
||||
FullName: "John Zoidberg", |
||||
Email: "zoidberg@planetexpress.com", |
||||
}, |
||||
{ |
||||
UserName: "amy", |
||||
Password: "amy", |
||||
FullName: "Amy Kroker", |
||||
Email: "amy@planetexpress.com", |
||||
}, |
||||
} |
||||
|
||||
func skipLDAPTests() bool { |
||||
return os.Getenv("TEST_LDAP") != "1" |
||||
} |
||||
|
||||
func getLDAPServerHost() string { |
||||
host := os.Getenv("TEST_LDAP_HOST") |
||||
if len(host) == 0 { |
||||
host = "ldap" |
||||
} |
||||
return host |
||||
} |
||||
|
||||
func addAuthSourceLDAP(t *testing.T) { |
||||
session := loginUser(t, "user1") |
||||
csrf := GetCSRF(t, session, "/admin/auths/new") |
||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", map[string]string{ |
||||
"_csrf": csrf, |
||||
"type": "2", |
||||
"name": "ldap", |
||||
"host": getLDAPServerHost(), |
||||
"port": "389", |
||||
"bind_dn": "uid=gitea,ou=service,dc=planetexpress,dc=com", |
||||
"bind_password": "password", |
||||
"user_base": "ou=people,dc=planetexpress,dc=com", |
||||
"filter": "(&(objectClass=inetOrgPerson)(memberOf=cn=git,ou=people,dc=planetexpress,dc=com)(uid=%s))", |
||||
"admin_filter": "(memberOf=cn=admin_staff,ou=people,dc=planetexpress,dc=com)", |
||||
"attribute_username": "uid", |
||||
"attribute_name": "givenName", |
||||
"attribute_surname": "sn", |
||||
"attribute_mail": "mail", |
||||
"is_sync_enabled": "on", |
||||
"is_active": "on", |
||||
}) |
||||
session.MakeRequest(t, req, http.StatusFound) |
||||
} |
||||
|
||||
func TestLDAPUserSignin(t *testing.T) { |
||||
if skipLDAPTests() { |
||||
t.Skip() |
||||
return |
||||
} |
||||
prepareTestEnv(t) |
||||
addAuthSourceLDAP(t) |
||||
|
||||
u := gitLDAPUsers[0] |
||||
|
||||
session := loginUserWithPassword(t, u.UserName, u.Password) |
||||
req := NewRequest(t, "GET", "/user/settings") |
||||
resp := session.MakeRequest(t, req, http.StatusOK) |
||||
|
||||
htmlDoc := NewHTMLParser(t, resp.Body) |
||||
|
||||
assert.Equal(t, u.UserName, htmlDoc.GetInputValueByName("name")) |
||||
assert.Equal(t, u.FullName, htmlDoc.GetInputValueByName("full_name")) |
||||
assert.Equal(t, u.Email, htmlDoc.GetInputValueByName("email")) |
||||
} |
||||
|
||||
func TestLDAPUserSync(t *testing.T) { |
||||
if skipLDAPTests() { |
||||
t.Skip() |
||||
return |
||||
} |
||||
prepareTestEnv(t) |
||||
addAuthSourceLDAP(t) |
||||
models.SyncExternalUsers() |
||||
|
||||
session := loginUser(t, "user1") |
||||
// Check if users exists
|
||||
for _, u := range gitLDAPUsers { |
||||
req := NewRequest(t, "GET", "/admin/users?q="+u.UserName) |
||||
resp := session.MakeRequest(t, req, http.StatusOK) |
||||
|
||||
htmlDoc := NewHTMLParser(t, resp.Body) |
||||
|
||||
tr := htmlDoc.doc.Find("table.table tbody tr") |
||||
if !assert.True(t, tr.Length() == 1) { |
||||
continue |
||||
} |
||||
tds := tr.Find("td") |
||||
if !assert.True(t, tds.Length() > 0) { |
||||
continue |
||||
} |
||||
assert.Equal(t, u.UserName, strings.TrimSpace(tds.Find("td:nth-child(2) a").Text())) |
||||
assert.Equal(t, u.Email, strings.TrimSpace(tds.Find("td:nth-child(3) span").Text())) |
||||
if u.IsAdmin { |
||||
assert.True(t, tds.Find("td:nth-child(5) i").HasClass("fa-check-square-o")) |
||||
} else { |
||||
assert.True(t, tds.Find("td:nth-child(5) i").HasClass("fa-square-o")) |
||||
} |
||||
} |
||||
|
||||
// Check if no users exist
|
||||
for _, u := range otherLDAPUsers { |
||||
req := NewRequest(t, "GET", "/admin/users?q="+u.UserName) |
||||
resp := session.MakeRequest(t, req, http.StatusOK) |
||||
|
||||
htmlDoc := NewHTMLParser(t, resp.Body) |
||||
|
||||
tr := htmlDoc.doc.Find("table.table tbody tr") |
||||
assert.True(t, tr.Length() == 0) |
||||
} |
||||
} |
||||
|
||||
func TestLDAPUserSigninFailed(t *testing.T) { |
||||
if skipLDAPTests() { |
||||
t.Skip() |
||||
return |
||||
} |
||||
prepareTestEnv(t) |
||||
addAuthSourceLDAP(t) |
||||
|
||||
u := otherLDAPUsers[0] |
||||
|
||||
testLoginFailed(t, u.UserName, u.Password, i18n.Tr("en", "form.username_password_incorrect")) |
||||
} |
@ -0,0 +1,8 @@ |
||||
- |
||||
id: 1 |
||||
assignee_id: 1 |
||||
issue_id: 1 |
||||
- |
||||
id: 2 |
||||
assignee_id: 1 |
||||
issue_id: 6 |
@ -0,0 +1 @@ |
||||
[] # empty |
@ -0,0 +1,263 @@ |
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models |
||||
|
||||
import ( |
||||
"fmt" |
||||
|
||||
"code.gitea.io/gitea/modules/log" |
||||
|
||||
api "code.gitea.io/sdk/gitea" |
||||
"github.com/go-xorm/xorm" |
||||
) |
||||
|
||||
// IssueAssignees saves all issue assignees
|
||||
type IssueAssignees struct { |
||||
ID int64 `xorm:"pk autoincr"` |
||||
AssigneeID int64 `xorm:"INDEX"` |
||||
IssueID int64 `xorm:"INDEX"` |
||||
} |
||||
|
||||
// This loads all assignees of an issue
|
||||
func (issue *Issue) loadAssignees(e Engine) (err error) { |
||||
// Reset maybe preexisting assignees
|
||||
issue.Assignees = []*User{} |
||||
|
||||
err = e.Table("`user`"). |
||||
Join("INNER", "issue_assignees", "assignee_id = `user`.id"). |
||||
Where("issue_assignees.issue_id = ?", issue.ID). |
||||
Find(&issue.Assignees) |
||||
|
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
// Check if we have at least one assignee and if yes put it in as `Assignee`
|
||||
if len(issue.Assignees) > 0 { |
||||
issue.Assignee = issue.Assignees[0] |
||||
} |
||||
|
||||
return |
||||
} |
||||
|
||||
// GetAssigneesByIssue returns everyone assigned to that issue
|
||||
func GetAssigneesByIssue(issue *Issue) (assignees []*User, err error) { |
||||
err = issue.loadAssignees(x) |
||||
if err != nil { |
||||
return assignees, err |
||||
} |
||||
|
||||
return issue.Assignees, nil |
||||
} |
||||
|
||||
// IsUserAssignedToIssue returns true when the user is assigned to the issue
|
||||
func IsUserAssignedToIssue(issue *Issue, user *User) (isAssigned bool, err error) { |
||||
isAssigned, err = x.Exist(&IssueAssignees{IssueID: issue.ID, AssigneeID: user.ID}) |
||||
return |
||||
} |
||||
|
||||
// DeleteNotPassedAssignee deletes all assignees who aren't passed via the "assignees" array
|
||||
func DeleteNotPassedAssignee(issue *Issue, doer *User, assignees []*User) (err error) { |
||||
var found bool |
||||
|
||||
for _, assignee := range issue.Assignees { |
||||
|
||||
found = false |
||||
for _, alreadyAssignee := range assignees { |
||||
if assignee.ID == alreadyAssignee.ID { |
||||
found = true |
||||
break |
||||
} |
||||
} |
||||
|
||||
if !found { |
||||
// This function also does comments and hooks, which is why we call it seperatly instead of directly removing the assignees here
|
||||
if err := UpdateAssignee(issue, doer, assignee.ID); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
} |
||||
|
||||
return nil |
||||
} |
||||
|
||||
// MakeAssigneeList concats a string with all names of the assignees. Useful for logs.
|
||||
func MakeAssigneeList(issue *Issue) (assigneeList string, err error) { |
||||
err = issue.loadAssignees(x) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
|
||||
for in, assignee := range issue.Assignees { |
||||
assigneeList += assignee.Name |
||||
|
||||
if len(issue.Assignees) > (in + 1) { |
||||
assigneeList += ", " |
||||
} |
||||
} |
||||
return |
||||
} |
||||
|
||||
// ClearAssigneeByUserID deletes all assignments of an user
|
||||
func clearAssigneeByUserID(sess *xorm.Session, userID int64) (err error) { |
||||
_, err = sess.Delete(&IssueAssignees{AssigneeID: userID}) |
||||
return |
||||
} |
||||
|
||||
// AddAssigneeIfNotAssigned adds an assignee only if he isn't aleady assigned to the issue
|
||||
func AddAssigneeIfNotAssigned(issue *Issue, doer *User, assigneeID int64) (err error) { |
||||
// Check if the user is already assigned
|
||||
isAssigned, err := IsUserAssignedToIssue(issue, &User{ID: assigneeID}) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
if !isAssigned { |
||||
return issue.ChangeAssignee(doer, assigneeID) |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
// UpdateAssignee deletes or adds an assignee to an issue
|
||||
func UpdateAssignee(issue *Issue, doer *User, assigneeID int64) (err error) { |
||||
return issue.ChangeAssignee(doer, assigneeID) |
||||
} |
||||
|
||||
// ChangeAssignee changes the Assignee of this issue.
|
||||
func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) { |
||||
sess := x.NewSession() |
||||
defer sess.Close() |
||||
|
||||
if err := sess.Begin(); err != nil { |
||||
return err |
||||
} |
||||
|
||||
if err := issue.changeAssignee(sess, doer, assigneeID); err != nil { |
||||
return err |
||||
} |
||||
|
||||
return sess.Commit() |
||||
} |
||||
|
||||
func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID int64) (err error) { |
||||
|
||||
// Update the assignee
|
||||
removed, err := updateIssueAssignee(sess, issue, assigneeID) |
||||
if err != nil { |
||||
return fmt.Errorf("UpdateIssueUserByAssignee: %v", err) |
||||
} |
||||
|
||||
// Repo infos
|
||||
if err = issue.loadRepo(sess); err != nil { |
||||
return fmt.Errorf("loadRepo: %v", err) |
||||
} |
||||
|
||||
// Comment
|
||||
if _, err = createAssigneeComment(sess, doer, issue.Repo, issue, assigneeID, removed); err != nil { |
||||
return fmt.Errorf("createAssigneeComment: %v", err) |
||||
} |
||||
|
||||
if issue.IsPull { |
||||
issue.PullRequest = &PullRequest{Issue: issue} |
||||
apiPullRequest := &api.PullRequestPayload{ |
||||
Index: issue.Index, |
||||
PullRequest: issue.PullRequest.APIFormat(), |
||||
Repository: issue.Repo.APIFormat(AccessModeNone), |
||||
Sender: doer.APIFormat(), |
||||
} |
||||
if removed { |
||||
apiPullRequest.Action = api.HookIssueUnassigned |
||||
} else { |
||||
apiPullRequest.Action = api.HookIssueAssigned |
||||
} |
||||
if err := PrepareWebhooks(issue.Repo, HookEventPullRequest, apiPullRequest); err != nil { |
||||
log.Error(4, "PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err) |
||||
return nil |
||||
} |
||||
} |
||||
go HookQueue.Add(issue.RepoID) |
||||
return nil |
||||
} |
||||
|
||||
// UpdateAPIAssignee is a helper function to add or delete one or multiple issue assignee(s)
|
||||
// Deleting is done the Github way (quote from their api documentation):
|
||||
// https://developer.github.com/v3/issues/#edit-an-issue
|
||||
// "assignees" (array): Logins for Users to assign to this issue.
|
||||
// Pass one or more user logins to replace the set of assignees on this Issue.
|
||||
// Send an empty array ([]) to clear all assignees from the Issue.
|
||||
func UpdateAPIAssignee(issue *Issue, oneAssignee string, multipleAssignees []string, doer *User) (err error) { |
||||
var allNewAssignees []*User |
||||
|
||||
// Keep the old assignee thingy for compatibility reasons
|
||||
if oneAssignee != "" { |
||||
// Prevent double adding assignees
|
||||
var isDouble bool |
||||
for _, assignee := range multipleAssignees { |
||||
if assignee == oneAssignee { |
||||
isDouble = true |
||||
break |
||||
} |
||||
} |
||||
|
||||
if !isDouble { |
||||
multipleAssignees = append(multipleAssignees, oneAssignee) |
||||
} |
||||
} |
||||
|
||||
// Loop through all assignees to add them
|
||||
for _, assigneeName := range multipleAssignees { |
||||
assignee, err := GetUserByName(assigneeName) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
allNewAssignees = append(allNewAssignees, assignee) |
||||
} |
||||
|
||||
// Delete all old assignees not passed
|
||||
if err = DeleteNotPassedAssignee(issue, doer, allNewAssignees); err != nil { |
||||
return err |
||||
} |
||||
|
||||
// Add all new assignees
|
||||
// Update the assignee. The function will check if the user exists, is already
|
||||
// assigned (which he shouldn't as we deleted all assignees before) and
|
||||
// has access to the repo.
|
||||
for _, assignee := range allNewAssignees { |
||||
// Extra method to prevent double adding (which would result in removing)
|
||||
err = AddAssigneeIfNotAssigned(issue, doer, assignee.ID) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} |
||||
|
||||
return |
||||
} |
||||
|
||||
// MakeIDsFromAPIAssigneesToAdd returns an array with all assignee IDs
|
||||
func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string) (assigneeIDs []int64, err error) { |
||||
|
||||
// Keeping the old assigning method for compatibility reasons
|
||||
if oneAssignee != "" { |
||||
|
||||
// Prevent double adding assignees
|
||||
var isDouble bool |
||||
for _, assignee := range multipleAssignees { |
||||
if assignee == oneAssignee { |
||||
isDouble = true |
||||
break |
||||
} |
||||
} |
||||
|
||||
if !isDouble { |
||||
multipleAssignees = append(multipleAssignees, oneAssignee) |
||||
} |
||||
} |
||||
|
||||
// Get the IDs of all assignees
|
||||
assigneeIDs = GetUserIDsByNames(multipleAssignees) |
||||
|
||||
return |
||||
} |
@ -0,0 +1,71 @@ |
||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestUpdateAssignee(t *testing.T) { |
||||
assert.NoError(t, PrepareTestDatabase()) |
||||
|
||||
// Fake issue with assignees
|
||||
issue, err := GetIssueByID(1) |
||||
assert.NoError(t, err) |
||||
|
||||
// Assign multiple users
|
||||
user2, err := GetUserByID(2) |
||||
assert.NoError(t, err) |
||||
err = UpdateAssignee(issue, &User{ID: 1}, user2.ID) |
||||
assert.NoError(t, err) |
||||
|
||||
user3, err := GetUserByID(3) |
||||
assert.NoError(t, err) |
||||
err = UpdateAssignee(issue, &User{ID: 1}, user3.ID) |
||||
assert.NoError(t, err) |
||||
|
||||
user1, err := GetUserByID(1) // This user is already assigned (see the definition in fixtures), so running UpdateAssignee should unassign him
|
||||
assert.NoError(t, err) |
||||
err = UpdateAssignee(issue, &User{ID: 1}, user1.ID) |
||||
assert.NoError(t, err) |
||||
|
||||
// Check if he got removed
|
||||
isAssigned, err := IsUserAssignedToIssue(issue, user1) |
||||
assert.NoError(t, err) |
||||
assert.False(t, isAssigned) |
||||
|
||||
// Check if they're all there
|
||||
assignees, err := GetAssigneesByIssue(issue) |
||||
assert.NoError(t, err) |
||||
|
||||
var expectedAssignees []*User |
||||
expectedAssignees = append(expectedAssignees, user2) |
||||
expectedAssignees = append(expectedAssignees, user3) |
||||
|
||||
for in, assignee := range assignees { |
||||
assert.Equal(t, assignee.ID, expectedAssignees[in].ID) |
||||
} |
||||
|
||||
// Check if the user is assigned
|
||||
isAssigned, err = IsUserAssignedToIssue(issue, user2) |
||||
assert.NoError(t, err) |
||||
assert.True(t, isAssigned) |
||||
|
||||
// This user should not be assigned
|
||||
isAssigned, err = IsUserAssignedToIssue(issue, &User{ID: 4}) |
||||
assert.NoError(t, err) |
||||
assert.False(t, isAssigned) |
||||
|
||||
// Clean everyone
|
||||
err = DeleteNotPassedAssignee(issue, user1, []*User{}) |
||||
assert.NoError(t, err) |
||||
|
||||
// Check they're gone
|
||||
assignees, err = GetAssigneesByIssue(issue) |
||||
assert.NoError(t, err) |
||||
assert.Equal(t, 0, len(assignees)) |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,665 @@ |
||||
{ |
||||
"requires": true, |
||||
"lockfileVersion": 1, |
||||
"dependencies": { |
||||
"amdefine": { |
||||
"version": "1.0.1", |
||||
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", |
||||
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", |
||||
"dev": true |
||||
}, |
||||
"asap": { |
||||
"version": "2.0.6", |
||||
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", |
||||
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"asn1": { |
||||
"version": "0.2.3", |
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", |
||||
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"asynckit": { |
||||
"version": "0.4.0", |
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", |
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"aws4": { |
||||
"version": "1.7.0", |
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", |
||||
"integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"bcrypt-pbkdf": { |
||||
"version": "1.0.1", |
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", |
||||
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"tweetnacl": "0.14.5" |
||||
} |
||||
}, |
||||
"caseless": { |
||||
"version": "0.12.0", |
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", |
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"clean-css": { |
||||
"version": "3.4.28", |
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", |
||||
"integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", |
||||
"dev": true, |
||||
"requires": { |
||||
"commander": "2.8.1", |
||||
"source-map": "0.4.4" |
||||
}, |
||||
"dependencies": { |
||||
"source-map": { |
||||
"version": "0.4.4", |
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", |
||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", |
||||
"dev": true, |
||||
"requires": { |
||||
"amdefine": "1.0.1" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
"co": { |
||||
"version": "4.6.0", |
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", |
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"combined-stream": { |
||||
"version": "1.0.6", |
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", |
||||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", |
||||
"dev": true, |
||||
"requires": { |
||||
"delayed-stream": "1.0.0" |
||||
} |
||||
}, |
||||
"commander": { |
||||
"version": "2.8.1", |
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", |
||||
"integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", |
||||
"dev": true, |
||||
"requires": { |
||||
"graceful-readlink": "1.0.1" |
||||
} |
||||
}, |
||||
"core-util-is": { |
||||
"version": "1.0.2", |
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", |
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"dashdash": { |
||||
"version": "1.14.1", |
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", |
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"assert-plus": "1.0.0" |
||||
}, |
||||
"dependencies": { |
||||
"assert-plus": { |
||||
"version": "1.0.0", |
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", |
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", |
||||
"dev": true, |
||||
"optional": true |
||||
} |
||||
} |
||||
}, |
||||
"delayed-stream": { |
||||
"version": "1.0.0", |
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", |
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", |
||||
"dev": true |
||||
}, |
||||
"ecc-jsbn": { |
||||
"version": "0.1.1", |
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", |
||||
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"jsbn": "0.1.1" |
||||
} |
||||
}, |
||||
"errno": { |
||||
"version": "0.1.7", |
||||
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", |
||||
"integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"prr": "1.0.1" |
||||
} |
||||
}, |
||||
"extend": { |
||||
"version": "3.0.1", |
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", |
||||
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"extsprintf": { |
||||
"version": "1.3.0", |
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", |
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", |
||||
"dev": true |
||||
}, |
||||
"fast-deep-equal": { |
||||
"version": "1.1.0", |
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", |
||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"fast-json-stable-stringify": { |
||||
"version": "2.0.0", |
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", |
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"forever-agent": { |
||||
"version": "0.6.1", |
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", |
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"getpass": { |
||||
"version": "0.1.7", |
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", |
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"assert-plus": "1.0.0" |
||||
}, |
||||
"dependencies": { |
||||
"assert-plus": { |
||||
"version": "1.0.0", |
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", |
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", |
||||
"dev": true, |
||||
"optional": true |
||||
} |
||||
} |
||||
}, |
||||
"graceful-fs": { |
||||
"version": "4.1.11", |
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", |
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"graceful-readlink": { |
||||
"version": "1.0.1", |
||||
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", |
||||
"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", |
||||
"dev": true |
||||
}, |
||||
"image-size": { |
||||
"version": "0.5.5", |
||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", |
||||
"integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"is-typedarray": { |
||||
"version": "1.0.0", |
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", |
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"isstream": { |
||||
"version": "0.1.2", |
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", |
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"jsbn": { |
||||
"version": "0.1.1", |
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", |
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"json-schema": { |
||||
"version": "0.2.3", |
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", |
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"json-schema-traverse": { |
||||
"version": "0.3.1", |
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", |
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"json-stringify-safe": { |
||||
"version": "5.0.1", |
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", |
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"jsprim": { |
||||
"version": "1.4.1", |
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", |
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"assert-plus": "1.0.0", |
||||
"extsprintf": "1.3.0", |
||||
"json-schema": "0.2.3", |
||||
"verror": "1.10.0" |
||||
}, |
||||
"dependencies": { |
||||
"assert-plus": { |
||||
"version": "1.0.0", |
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", |
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", |
||||
"dev": true, |
||||
"optional": true |
||||
} |
||||
} |
||||
}, |
||||
"less": { |
||||
"version": "3.0.4", |
||||
"resolved": "https://registry.npmjs.org/less/-/less-3.0.4.tgz", |
||||
"integrity": "sha512-q3SyEnPKbk9zh4l36PGeW2fgynKu+FpbhiUNx/yaiBUQ3V0CbACCgb9FzYWcRgI2DJlP6eI4jc8XPrCTi55YcQ==", |
||||
"dev": true, |
||||
"requires": { |
||||
"errno": "0.1.7", |
||||
"graceful-fs": "4.1.11", |
||||
"image-size": "0.5.5", |
||||
"mime": "1.6.0", |
||||
"mkdirp": "0.5.1", |
||||
"promise": "7.3.1", |
||||
"request": "2.85.0", |
||||
"source-map": "0.6.1" |
||||
}, |
||||
"dependencies": { |
||||
"ajv": { |
||||
"version": "5.5.2", |
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", |
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"co": "4.6.0", |
||||
"fast-deep-equal": "1.1.0", |
||||
"fast-json-stable-stringify": "2.0.0", |
||||
"json-schema-traverse": "0.3.1" |
||||
} |
||||
}, |
||||
"assert-plus": { |
||||
"version": "1.0.0", |
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", |
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"aws-sign2": { |
||||
"version": "0.7.0", |
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", |
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"boom": { |
||||
"version": "4.3.1", |
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", |
||||
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"hoek": "4.2.1" |
||||
} |
||||
}, |
||||
"cryptiles": { |
||||
"version": "3.1.2", |
||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", |
||||
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"boom": "5.2.0" |
||||
}, |
||||
"dependencies": { |
||||
"boom": { |
||||
"version": "5.2.0", |
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", |
||||
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"hoek": "4.2.1" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
"form-data": { |
||||
"version": "2.3.2", |
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", |
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"asynckit": "0.4.0", |
||||
"combined-stream": "1.0.6", |
||||
"mime-types": "2.1.18" |
||||
} |
||||
}, |
||||
"har-schema": { |
||||
"version": "2.0.0", |
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", |
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"har-validator": { |
||||
"version": "5.0.3", |
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", |
||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"ajv": "5.5.2", |
||||
"har-schema": "2.0.0" |
||||
} |
||||
}, |
||||
"hawk": { |
||||
"version": "6.0.2", |
||||
"resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", |
||||
"integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"boom": "4.3.1", |
||||
"cryptiles": "3.1.2", |
||||
"hoek": "4.2.1", |
||||
"sntp": "2.1.0" |
||||
} |
||||
}, |
||||
"hoek": { |
||||
"version": "4.2.1", |
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", |
||||
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", |
||||
"dev": true |
||||
}, |
||||
"http-signature": { |
||||
"version": "1.2.0", |
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", |
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"assert-plus": "1.0.0", |
||||
"jsprim": "1.4.1", |
||||
"sshpk": "1.14.1" |
||||
} |
||||
}, |
||||
"performance-now": { |
||||
"version": "2.1.0", |
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", |
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"qs": { |
||||
"version": "6.5.2", |
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", |
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"request": { |
||||
"version": "2.85.0", |
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", |
||||
"integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"aws-sign2": "0.7.0", |
||||
"aws4": "1.7.0", |
||||
"caseless": "0.12.0", |
||||
"combined-stream": "1.0.6", |
||||
"extend": "3.0.1", |
||||
"forever-agent": "0.6.1", |
||||
"form-data": "2.3.2", |
||||
"har-validator": "5.0.3", |
||||
"hawk": "6.0.2", |
||||
"http-signature": "1.2.0", |
||||
"is-typedarray": "1.0.0", |
||||
"isstream": "0.1.2", |
||||
"json-stringify-safe": "5.0.1", |
||||
"mime-types": "2.1.18", |
||||
"oauth-sign": "0.8.2", |
||||
"performance-now": "2.1.0", |
||||
"qs": "6.5.2", |
||||
"safe-buffer": "5.1.2", |
||||
"stringstream": "0.0.5", |
||||
"tough-cookie": "2.3.4", |
||||
"tunnel-agent": "0.6.0", |
||||
"uuid": "3.2.1" |
||||
} |
||||
}, |
||||
"sntp": { |
||||
"version": "2.1.0", |
||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", |
||||
"integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"hoek": "4.2.1" |
||||
} |
||||
}, |
||||
"source-map": { |
||||
"version": "0.6.1", |
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", |
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", |
||||
"dev": true, |
||||
"optional": true |
||||
} |
||||
} |
||||
}, |
||||
"less-plugin-clean-css": { |
||||
"version": "1.5.1", |
||||
"resolved": "https://registry.npmjs.org/less-plugin-clean-css/-/less-plugin-clean-css-1.5.1.tgz", |
||||
"integrity": "sha1-zFeveqM5iVflbezr5jy2DCNClwM=", |
||||
"dev": true, |
||||
"requires": { |
||||
"clean-css": "3.4.28" |
||||
} |
||||
}, |
||||
"mime": { |
||||
"version": "1.6.0", |
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", |
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"mime-db": { |
||||
"version": "1.33.0", |
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", |
||||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", |
||||
"dev": true |
||||
}, |
||||
"mime-types": { |
||||
"version": "2.1.18", |
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", |
||||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", |
||||
"dev": true, |
||||
"requires": { |
||||
"mime-db": "1.33.0" |
||||
} |
||||
}, |
||||
"minimist": { |
||||
"version": "0.0.8", |
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", |
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"mkdirp": { |
||||
"version": "0.5.1", |
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", |
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"minimist": "0.0.8" |
||||
} |
||||
}, |
||||
"oauth-sign": { |
||||
"version": "0.8.2", |
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", |
||||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"promise": { |
||||
"version": "7.3.1", |
||||
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", |
||||
"integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"asap": "2.0.6" |
||||
} |
||||
}, |
||||
"prr": { |
||||
"version": "1.0.1", |
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", |
||||
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"punycode": { |
||||
"version": "1.4.1", |
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", |
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"safe-buffer": { |
||||
"version": "5.1.2", |
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", |
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", |
||||
"dev": true |
||||
}, |
||||
"sshpk": { |
||||
"version": "1.14.1", |
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", |
||||
"integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"asn1": "0.2.3", |
||||
"assert-plus": "1.0.0", |
||||
"bcrypt-pbkdf": "1.0.1", |
||||
"dashdash": "1.14.1", |
||||
"ecc-jsbn": "0.1.1", |
||||
"getpass": "0.1.7", |
||||
"jsbn": "0.1.1", |
||||
"tweetnacl": "0.14.5" |
||||
}, |
||||
"dependencies": { |
||||
"assert-plus": { |
||||
"version": "1.0.0", |
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", |
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", |
||||
"dev": true, |
||||
"optional": true |
||||
} |
||||
} |
||||
}, |
||||
"stringstream": { |
||||
"version": "0.0.5", |
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", |
||||
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"tough-cookie": { |
||||
"version": "2.3.4", |
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", |
||||
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"punycode": "1.4.1" |
||||
} |
||||
}, |
||||
"tunnel-agent": { |
||||
"version": "0.6.0", |
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", |
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"safe-buffer": "5.1.2" |
||||
} |
||||
}, |
||||
"tweetnacl": { |
||||
"version": "0.14.5", |
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", |
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"uuid": { |
||||
"version": "3.2.1", |
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", |
||||
"integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", |
||||
"dev": true, |
||||
"optional": true |
||||
}, |
||||
"verror": { |
||||
"version": "1.10.0", |
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", |
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", |
||||
"dev": true, |
||||
"optional": true, |
||||
"requires": { |
||||
"assert-plus": "1.0.0", |
||||
"core-util-is": "1.0.2", |
||||
"extsprintf": "1.3.0" |
||||
}, |
||||
"dependencies": { |
||||
"assert-plus": { |
||||
"version": "1.0.0", |
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", |
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", |
||||
"dev": true, |
||||
"optional": true |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,7 +1,7 @@ |
||||
{ |
||||
"license": "MIT", |
||||
"devDependencies": { |
||||
"less": "^2.7.2", |
||||
"less": "^3.0.4", |
||||
"less-plugin-clean-css": "^1.5.1" |
||||
} |
||||
} |
||||
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,66 @@ |
||||
APP_NAME = Gitea: Go Git Service |
||||
RUN_USER = root |
||||
RUN_MODE = prod |
||||
CUSTOM_PATH = SNAP_DIR_DATA/custom |
||||
|
||||
[server] |
||||
DOMAIN = localhost |
||||
PROTOCOL = http |
||||
HTTP_PORT = 3001 |
||||
ROOT_URL = http://localhost:3001/ |
||||
DISABLE_SSH = false |
||||
SSH_PORT = 22 |
||||
STATIC_ROOT_PATH = SNAP_DIR_DATA/static |
||||
APP_DATA_PATH = SNAP_DIR_COMMON/data |
||||
SSH_ROOT = SNAP_DIR_COMMON/ssh |
||||
SSH_KEY_TEST_PATH = SNAP_DIR_DATA/sshkeytest |
||||
|
||||
[database] |
||||
DB_TYPE = sqlite3 |
||||
PATH = SNAP_DIR_COMMON/gitea.db |
||||
|
||||
[repository] |
||||
ROOT = SNAP_DIR_COMMON/repositories/data |
||||
|
||||
[repository.upload] |
||||
ENABLED = true |
||||
ALLOWED_TYPES = "image/jpeg|image/png" |
||||
FILE_MAX_SIZE = 10 |
||||
MAX_FILES = 5 |
||||
TEMP_PATH = SNAP_DIR_COMMON/repositories/tmp |
||||
|
||||
[release.attachment] |
||||
PATH = SNAP_DIR_COMMON/releases/attachments |
||||
|
||||
[smartypants] |
||||
ENABLED = true |
||||
|
||||
[indexer] |
||||
ISSUE_INDEXER_PATH = SNAP_DIR_COMMON/indexers/issues.bleve |
||||
|
||||
|
||||
[mailer] |
||||
ENABLED = false |
||||
|
||||
[service] |
||||
REGISTER_EMAIL_CONFIRM = false |
||||
ENABLE_NOTIFY_MAIL = false |
||||
DISABLE_REGISTRATION = false |
||||
ENABLE_CAPTCHA = false |
||||
REQUIRE_SIGNIN_VIEW = false |
||||
|
||||
[picture] |
||||
AVATAR_UPLOAD_PATH = SNAP_DIR_COMMON/pictures/avatars |
||||
DISABLE_GRAVATAR = true |
||||
ENABLE_FEDERATED_AVATAR = false |
||||
|
||||
[attachment] |
||||
PATH = SNAP_DIR_COMMON/attachments |
||||
|
||||
[session] |
||||
PROVIDER = memory |
||||
|
||||
[log] |
||||
MODE = file |
||||
LEVEL = Trace |
||||
ROOT_PATH = SNAP_DIR_COMMON/log |
@ -0,0 +1,126 @@ |
||||
#!/bin/bash |
||||
if snapctl get gitea.snap.custom; then |
||||
cdir=$(snapctl get gitea.snap.custom) |
||||
else |
||||
cdir=$SNAP_COMMON |
||||
fi |
||||
|
||||
cfg="$cdir/conf/app.ini" |
||||
bak="$cdir/conf/app.ini.bak-$(date -Ins)" |
||||
basecfg="$SNAP/snap/helpers/app.ini" |
||||
smp="$SNAP/gitea/custom/conf/app.ini.sample" |
||||
|
||||
function toSnap() { |
||||
OIFS=$IFS |
||||
IFS=' |
||||
' |
||||
category="none" |
||||
src="$cfg" |
||||
[[ "$1" = "init" ]] && src="$smp" |
||||
[[ "$1" = "snap" ]] && src="$basecfg" |
||||
|
||||
for l in $(sed 's_;\([A-Z]*\)_\1_g' $src | grep -v -e '^;' -e '^$'); do |
||||
if echo $l | grep -q '^[[]'; then |
||||
category=$(CatToSnap "$l") |
||||
elif echo $l | grep -q '^[A-Z]'; then |
||||
option=$(OptToSnap "$l") |
||||
value=$(ValToSnap "$l") |
||||
if [[ $category = "none" ]]; then |
||||
snapctl set "$option=$value" |
||||
else |
||||
snapctl set "$category.$option=$value" |
||||
fi |
||||
fi |
||||
done |
||||
IFS=$OIFS |
||||
} |
||||
|
||||
function toIni() { |
||||
OIFS=$IFS |
||||
IFS=' |
||||
' |
||||
category="none"; option="none"; catUnset=true |
||||
src=$smp |
||||
[[ -f $cfg ]] && src="$cfg" |
||||
tmpIni="$cfg.tmp" |
||||
[[ -f $src ]] && cp "$src" "$tmpIni" |
||||
cp $tmpIni $bak |
||||
echo '' > $cfg |
||||
for l in $(grep -v -e '^;' -e '^$' $tmpIni); do |
||||
if echo $l | grep -q '^[[]'; then |
||||
category=$(CatToSnap "$l") |
||||
catUnset=true |
||||
elif echo $l | grep -q '^[A-Z]'; then |
||||
option=$(OptToSnap "$l") |
||||
if [[ $category = "none" ]]; then |
||||
value=$(snapctl get $option) |
||||
echo $(OptToIni "$option") = $value >> $cfg |
||||
else |
||||
value=$(snapctl get $category.$option) |
||||
if $catUnset; then |
||||
echo "" >> $cfg |
||||
echo "[$(CatToIni "$category")]" >> $cfg |
||||
catUnset=false |
||||
fi |
||||
echo $(OptToIni "$option") = $value >> $cfg |
||||
fi |
||||
fi |
||||
done; |
||||
IFS=$OIFS |
||||
} |
||||
|
||||
function CatToSnap { |
||||
ret=$(echo "$1" \ |
||||
| grep -oP '[A-Za-z0-9._]+' \ |
||||
| sed 's|\.|-|g' \ |
||||
| sed 's|_|99|g') |
||||
echo $ret |
||||
} |
||||
function OptToSnap { |
||||
ret=$(echo "$1" \ |
||||
| grep -oP '^[A-Z_]+' \ |
||||
| tr '[:upper:]' '[:lower:]' \ |
||||
| sed 's|_|-|g') |
||||
echo $ret |
||||
} |
||||
function ValToSnap { |
||||
ret=$(echo "$1" \ |
||||
| grep -oP '=.*$' \ |
||||
| sed 's_^= __g' \ |
||||
| sed 's_^=__g' \ |
||||
| sed "s|SNAP_DIR_DATA|$SDATA|g" \ |
||||
| sed "s|SNAP_DIR_COMMON|$SCOMMON|g" \ |
||||
| sed 's|{}||g') |
||||
echo $ret |
||||
} |
||||
|
||||
function CatToIni { |
||||
ret=$(echo "$1" \ |
||||
| sed 's|-|.|g' \ |
||||
| sed 's|\ |_|g' \ |
||||
| sed 's|99|_|g') |
||||
echo $ret |
||||
} |
||||
function OptToIni { |
||||
ret=$(echo "$1" \ |
||||
| tr '[:lower:]' '[:upper:]' \ |
||||
| sed 's|-|_|g') |
||||
echo $ret |
||||
} |
||||
|
||||
[[ "$1" = "configure" ]] \ |
||||
&& toIni \ |
||||
&& exit 0 |
||||
|
||||
[[ "$1" = "install" ]] \ |
||||
&& echo "Initial Configuration..." \ |
||||
&& mkdir -p $SNAP_COMMON/conf \ |
||||
&& toSnap init \ |
||||
&& toSnap snap \ |
||||
&& toIni sample \ |
||||
&& exit 0 |
||||
|
||||
[[ "$1" = "save" ]] \ |
||||
&& echo "Saving current config..." \ |
||||
&& toSnap \ |
||||
&& exit 0 |
@ -0,0 +1,23 @@ |
||||
#!/bin/bash |
||||
|
||||
if ! env | grep -q root; then |
||||
echo " |
||||
+----------------------------------------+ |
||||
| You are not running gitea as root. | |
||||
| This is required for the snap package. | |
||||
| Please re-run as root. | |
||||
+----------------------------------------+ |
||||
" |
||||
$SNAP/gitea/gitea --help |
||||
exit 1 |
||||
fi |
||||
|
||||
# Set usernames for gitea |
||||
export USERNAME=root |
||||
export USER=root |
||||
|
||||
export GITEA_WORK_DIR=$(snapctl get gitea.snap.workdir) |
||||
export GITEA_CUSTOM=$(snapctl get gitea.snap.custom) |
||||
|
||||
$SNAP/bin/gconfig save |
||||
cd $SNAP/gitea; ./gitea $@ |
@ -0,0 +1,3 @@ |
||||
#!/bin/bash |
||||
|
||||
$SNAP/bin/gconfig configure |
@ -0,0 +1,45 @@ |
||||
#!/bin/bash |
||||
|
||||
export SDATA=$(echo $SNAP_DATA | sed "s|$SNAP_REVISION|current|") |
||||
export SCOMMON="$SNAP_COMMON" |
||||
export isRoot=`true` |
||||
snapctl set gitea.snap.workdir="$SDATA/custom" |
||||
snapctl set gitea.snap.custom="$SCOMMON" |
||||
|
||||
function mkDirCommon(){ |
||||
for dir in $@; do |
||||
mkdir -p "$SCOMMON/$dir" |
||||
done |
||||
} |
||||
|
||||
function mkdirData(){ |
||||
for dir in $@; do |
||||
mkdir -p "$SDATA/$dir" |
||||
if [ -d $SNAP/$dir ]; then |
||||
cp -r --preserve=mode \ |
||||
$SNAP/$dir/* \ |
||||
$SNAP/$dir/.[a-zA-Z0-9-]* \ |
||||
$SDATA/$dir/ 2> $SCOMMON/log/snap-mkdirData.log |
||||
fi |
||||
done |
||||
} |
||||
|
||||
mkDirCommon pictures \ |
||||
repositories \ |
||||
attachments \ |
||||
data \ |
||||
log |
||||
|
||||
mkdirData certs \ |
||||
sshkeytest \ |
||||
custom/conf \ |
||||
static/templates \ |
||||
static/scripts \ |
||||
static/public |
||||
|
||||
[[ -f $SNAP_COMMON/conf/app.ini ]] || $SNAP/bin/gconfig install |
||||
|
||||
# Configure Git to use the right templates |
||||
mkdir -p $SDATA/git/ |
||||
cp -r --preserve=mode $SNAP/usr/share/git-core/templates $SDATA/git/ |
||||
$SNAP/usr/bin/git config --global init.templateDir $SDATA/git/templates/ |
@ -0,0 +1,121 @@ |
||||
name: gitea |
||||
summary: Gitea - A painless self-hosted Git service |
||||
description: | |
||||
The goal of this project is to make the easiest, fastest, and most painless |
||||
way of setting up a self-hosted Git service. With Go, this can be done with |
||||
an independent binary distribution across ALL platforms that Go supports, |
||||
including Linux, Mac OS X, Windows and ARM. |
||||
|
||||
type: app |
||||
icon: public/img/gitea-lg.png |
||||
confinement: strict |
||||
grade: stable |
||||
|
||||
version: 'git' |
||||
|
||||
apps: |
||||
gitea: |
||||
command: bin/gitea |
||||
plugs: [network, network-bind] |
||||
web: |
||||
command: bin/gitea web |
||||
daemon: simple |
||||
plugs: [network, network-bind] |
||||
serv: |
||||
command: bin/gitea serv |
||||
plugs: [network, network-bind] |
||||
admin: |
||||
command: bin/gitea admin |
||||
plugs: [network, network-bind] |
||||
cert: |
||||
command: bin/gitea cert |
||||
hook: |
||||
command: bin/gitea hook |
||||
plugs: [network, network-bind] |
||||
dump: |
||||
command: bin/gitea dump |
||||
plugs: [home] |
||||
help: |
||||
command: bin/gitea --help |
||||
version: |
||||
command: bin/gitea --version |
||||
sqlite: |
||||
command: usr/bin/sqlite3 |
||||
|
||||
parts: |
||||
go: |
||||
source-tag: go1.8.3 |
||||
prime: |
||||
- -* |
||||
|
||||
gitea: |
||||
plugin: nil |
||||
source: . |
||||
source-type: git |
||||
after: [ go ] |
||||
stage-packages: [ git, sqlite3, openssh-client ] |
||||
build-packages: [ libpam0g-dev, libsqlite3-dev] |
||||
prepare: | |
||||
export PATH=$SNAPCRAFT_PART_INSTALL/../../go/install/bin:$PATH |
||||
export GOPATH=$SNAPCRAFT_PART_INSTALL/../go |
||||
export bld=$SNAPCRAFT_PART_INSTALL/../build |
||||
export src=$SNAPCRAFT_PART_INSTALL/../src |
||||
mkdir -p $GOPATH/src/code.gitea.io/gitea |
||||
cp -r $src/* $GOPATH/src/code.gitea.io/gitea |
||||
build: | |
||||
export PATH=$SNAPCRAFT_PART_INSTALL/../go/bin/:$SNAPCRAFT_PART_INSTALL/../../go/install/bin:$PATH |
||||
export GOPATH=$SNAPCRAFT_PART_INSTALL/../go |
||||
go get -u github.com/jteeuwen/go-bindata/... |
||||
cd $GOPATH/src/code.gitea.io/gitea |
||||
TAGS="bindata sqlite pam cert" make generate build |
||||
install: | |
||||
# Set Convenience Variables |
||||
src=$SNAPCRAFT_PART_INSTALL/../go/src/code.gitea.io/gitea |
||||
giteaBase=$SNAPCRAFT_PART_INSTALL/gitea |
||||
scurrent=/var/snap/$SNAPCRAFT_PROJECT_NAME/current |
||||
scommon=/var/snap/$SNAPCRAFT_PROJECT_NAME/common |
||||
# Copy build artifact and necessary files |
||||
mkdir -p $giteaBase/conf |
||||
# Workaround for gitea ignoring APP_DATA_PATH in app.ini after snap update. |
||||
ln -s $scurrent/custom $giteaBase/custom |
||||
ln -s $scommon/data $giteaBase/data |
||||
# Workaround for cmd/certs not knowing how to put files somewhere else |
||||
ln -s $scurrent/cert.pem $giteaBase/cert.pem |
||||
ln -s $scurrent/key.pem $giteaBase/key.pem |
||||
# Copy static content |
||||
mkdir -p $SNAPCRAFT_PART_INSTALL/static |
||||
cp $src/gitea $giteaBase/ |
||||
cp -r $src/LICENSE \ |
||||
$src/templates \ |
||||
$src/public \ |
||||
$src/scripts \ |
||||
$SNAPCRAFT_PART_INSTALL/static/ |
||||
cp -r $src/README.md \ |
||||
$src/LICENSE \ |
||||
$src/custom \ |
||||
$SNAPCRAFT_PART_INSTALL/ |
||||
prime: |
||||
- -etc |
||||
- -usr/lib/systemd |
||||
- -usr/lib/gcc |
||||
- -usr/lib/sasl2 |
||||
- -usr/lib/x86_64-linux-gnu/krb5 |
||||
- -usr/share/apport |
||||
- -usr/share/bash-completion |
||||
- -usr/share/doc |
||||
- -usr/share/git-core/contrib |
||||
- -usr/share/man |
||||
- -usr/share/upstart |
||||
- -var |
||||
|
||||
helpers: |
||||
plugin: dump |
||||
source: snap/helpers |
||||
organize: |
||||
simple_launcher.sh: bin/gitea |
||||
app.ini: gitea/snapApp.ini |
||||
configuration.sh: bin/gconfig |
||||
prime: |
||||
- bin/gitea |
||||
- bin/gconfig |
||||
- gitea/snapApp.ini |
Loading…
Reference in new issue