Merge branch 'master' into refactor_issues-subscription

This commit is contained in:
6543 2019-11-01 05:17:19 +01:00 committed by GitHub
commit 47ba722e19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
210 changed files with 7170 additions and 4719 deletions

1
.gitignore vendored
View File

@ -12,6 +12,7 @@ _test
# MS VSCode
.vscode
__debug_bin
# Architecture specific extensions/prefixes
*.[568vq]

View File

@ -4,6 +4,32 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.io).
## [1.10.0-RC2](https://github.com/go-gitea/gitea/releases/tag/v1.10.0-rc2) - 2019-10-30
* BREAKING
* Fix deadline on update issue or PR via API (#8698)
* Hide some user information via API if user doesn't have enough permission (#8655) (#8657)
* BUGFIXES
* Expose db.SetMaxOpenConns and allow non MySQL dbs to set conn pool params (#8528) (#8618)
* Fix milestone close timestamp (#8728) (#8730)
* Fix 500 when getting user as unauthenticated user (#8653) (#8663)
* Fix 'New Issue Missing Milestone Comment' (#8678) (#8681)
* Use AppSubUrl for more redirections (#8647) (#8651)
* Add SubURL to redirect path (#8632) (#8634)
* Fix template error on account page (#8562) (#8622)
* Allow externalID to be UUID (#8551) (#8624)
* Prevent removal of non-empty emoji panel following selection of duplicate (#8609) (#8623)
* Update heatmap fixtures to restore tests (#8615) (#8616)
* Ensure that diff stats can scroll independently of the diff (#8581) (#8621)
* Webhook: set Content-Type for application/x-www-form-urlencoded (#8600)
* Fix #8582 by handling empty repos (#8587) (#8594)
* Fix bug on pull requests when transfer head repository (#8564) (#8569)
* Add missed close in ServeBlobLFS (#8527) (#8542)
* Ensure that GitRepo is set on Empty repositories (#8539) (#8541)
* Fix migrate mirror 500 bug (#8526) (#8530)
* Fix password complexity regex for special characters (#8524)
* Prevent .code-view from overriding font on icon fonts (#8614) (#8627)
* Allow more than 255 characters for tokens in external_login_user table (#8554)
## [1.10.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.10.0-rc1) - 2019-10-14
* BREAKING
* Remove legacy handling of drone token (#8191)
@ -263,6 +289,30 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
* wiki - editor - add buttons 'inline code', 'empty checkbox', 'checked checkbox' (#7243)
* Fix Statuses API only shows first 10 statuses: Add paging and extend API GetCommitStatuses (#7141)
## [1.9.5](https://github.com/go-gitea/gitea/releases/tag/v1.9.5) - 2019-10-30
* BREAKING
* Hide some user information via API if user doesn't have enough permission (#8655) (#8658)
* BUGFIXES
* Fix milestone close timestamp (#8728) (#8731)
* Fix deadline on update issue or PR via API (#8699)
* Fix 'New Issue Missing Milestone Comment' (#8678) (#8682)
* Fix 500 when getting user as unauthenticated user (#8653) (#8662)
* Use AppSubUrl for more redirections (#8647) (#8652)
* Add SubURL to redirect path (#8632) (#8634) (#8640)
* Fix #8582 by handling empty repos (#8587) (#8593)
* Fix bug on pull requests when transfer head repository (#8571)
* Add missed close in ServeBlobLFS (#8527) (#8543)
* Return false if provided branch name is empty for IsBranchExist (#8485) (#8492)
* Create .ssh dir as necessary (#8369) (#8486) (#8489)
* Restore functionality for early gits (#7775) (#8476)
* Add check for empty set when dropping indexes during migration (#8475)
* Ensure Request Body Readers are closed in LFS server (#8454) (#8459)
* Ensure that LFS files are relative to the LFS content path (#8455) (#8458)
* SECURITY
* Ignore mentions for users with no access (#8395) (#8484)
* TESTING
* Update heatmap fixtures to restore tests (#8615) (#8617)
## [1.9.4](https://github.com/go-gitea/gitea/releases/tag/v1.9.4) - 2019-10-08
* BUGFIXES
* Highlight issue references (#8101) (#8404)

View File

@ -66,7 +66,7 @@ var (
},
cli.BoolFlag{
Name: "must-change-password",
Usage: "Force the user to change his/her password after initial login",
Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
},
cli.IntFlag{
Name: "random-password-length",

View File

@ -69,6 +69,10 @@ MAX_FILES = 5
[repository.pull-request]
; List of prefixes used in Pull Request title to mark them as Work In Progress
WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP]
; List of keywords used in Pull Request comments to automatically close a related issue
CLOSE_KEYWORDS=close,closes,closed,fix,fixes,fixed,resolve,resolves,resolved
; List of keywords used in Pull Request comments to automatically reopen a related issue
REOPEN_KEYWORDS=reopen,reopens,reopened
[repository.issue]
; List of reasons why a Pull Request or Issue can be locked
@ -475,6 +479,8 @@ DEFAULT_ORG_MEMBER_VISIBLE = false
; Default value for EnableDependencies
; Repositories will use dependencies by default depending on this setting
DEFAULT_ENABLE_DEPENDENCIES = true
; Dependencies can be added from any repository where the user is granted access or only from the current repository depending on this setting.
ALLOW_CROSS_REPOSITORY_DEPENDENCIES = true
; Enable heatmap on users profiles.
ENABLE_USER_HEATMAP = true
; Enable Timetracking

View File

@ -71,6 +71,10 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
- `WORK_IN_PROGRESS_PREFIXES`: **WIP:,\[WIP\]**: List of prefixes used in Pull Request
title to mark them as Work In Progress
- `CLOSE_KEYWORDS`: **close**, **closes**, **closed**, **fix**, **fixes**, **fixed**, **resolve**, **resolves**, **resolved**: List of
keywords used in Pull Request comments to automatically close a related issue
- `REOPEN_KEYWORDS`: **reopen**, **reopens**, **reopened**: List of keywords used in Pull Request comments to automatically reopen
a related issue
### Repository - Issue (`repository.issue`)
@ -293,6 +297,7 @@ relation to port exhaustion.
- `RECAPTCHA_SITEKEY`: **""**: Go to https://www.google.com/recaptcha/admin to get a sitekey for recaptcha.
- `RECAPTCHA_URL`: **https://www.google.com/recaptcha/**: Set the recaptcha url - allows the use of recaptcha net.
- `DEFAULT_ENABLE_DEPENDENCIES`: **true**: Enable this to have dependencies enabled by default.
- `ALLOW_CROSS_REPOSITORY_DEPENDENCIES` : **true** Enable this to allow dependencies on issues from any repository where the user is granted access.
- `ENABLE_USER_HEATMAP`: **true**: Enable this to display the heatmap on users profiles.
- `EMAIL_DOMAIN_WHITELIST`: **\<empty\>**: If non-empty, list of domain names that can only be used to register
on this instance.

9
go.mod
View File

@ -22,7 +22,6 @@ require (
github.com/blevesearch/go-porterstemmer v0.0.0-20141230013033-23a2c8e5cf1f // indirect
github.com/blevesearch/segment v0.0.0-20160105220820-db70c57796cc // indirect
github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26 // indirect
github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f
github.com/couchbase/vellum v0.0.0-20190111184608-e91b68ff3efe // indirect
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d // indirect
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect
@ -73,6 +72,7 @@ require (
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5
github.com/niklasfasching/go-org v0.1.7
github.com/oliamb/cutter v0.2.2
github.com/philhofer/fwd v1.0.0 // indirect
github.com/pkg/errors v0.8.1
@ -80,12 +80,13 @@ require (
github.com/prometheus/client_golang v1.1.0
github.com/prometheus/procfs v0.0.4 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 // indirect
github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff
github.com/russross/blackfriday v2.0.0+incompatible // indirect
github.com/russross/blackfriday/v2 v2.0.1
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
github.com/satori/go.uuid v1.2.0
github.com/sergi/go-diff v1.0.0
github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b // indirect
github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 // indirect
github.com/stretchr/testify v1.4.0
@ -100,7 +101,7 @@ require (
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b
golang.org/x/text v0.3.2

16
go.sum
View File

@ -86,8 +86,6 @@ github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26/go.mod h1:paBWMc
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 h1:U/lr3Dgy4WK+hNk4tyD+nuGjpVLPEHuJSFXMw11/HPA=
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f h1:REH9VH5ubNR0skLaOxK7TRJeRbE2dDfvaouQo8FsRcA=
github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f/go.mod h1:6QaC0vFoKWYDth94dHFNgRT2YkT5FHdQp/Yx15aAAi0=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/corbym/gocrest v1.0.3 h1:gwEdq6RkTmq+09CTuM29DfKOCtZ7G7bcyxs3IZ6EVdU=
github.com/corbym/gocrest v1.0.3/go.mod h1:maVFL5lbdS2PgfOQgGRWDYTeunSWQeiEgoNdTABShCs=
@ -425,6 +423,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY=
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/niklasfasching/go-org v0.1.6 h1:F521WcqRNl8OJumlgAnekZgERaTA2HpfOYYfVEKOeI8=
github.com/niklasfasching/go-org v0.1.6/go.mod h1:AsLD6X7djzRIz4/RFZu8vwRL0VGjUvGZCCH1Nz0VdrU=
github.com/niklasfasching/go-org v0.1.7 h1:t3V+3XnS/7BhKv/7SlMUa8FvAiq577/a1T3D7mLIRXE=
github.com/niklasfasching/go-org v0.1.7/go.mod h1:AsLD6X7djzRIz4/RFZu8vwRL0VGjUvGZCCH1Nz0VdrU=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/oliamb/cutter v0.2.2 h1:Lfwkya0HHNU1YLnGv2hTkzHfasrSMkgv4Dn+5rmlk3k=
github.com/oliamb/cutter v0.2.2/go.mod h1:4BenG2/4GuRBDbVm/OPahDVqbrOemzpPiG5mi1iryBU=
@ -487,8 +489,10 @@ github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001/go.mod h1:qq
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff h1:g9ZlAHmkc/h5So+OjNCkZWh+FjuKEOOOoyRkqlGA8+c=
github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
@ -499,6 +503,8 @@ github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b h1:4kg1wyftSKxLtnP
github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc h1:3wIrJvFb3Pf6B/2mDBnN1G5IfUVev4X5apadQlWOczE=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0=
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
@ -650,6 +656,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b h1:XfVGCX+0T4WOStkaOsJRllbsiImhB2jgVBGc9L0lPGc=
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271 h1:N66aaryRB3Ax92gH0v3hp1QYZ3zWWCCUR/j8Ifh45Ss=
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=

View File

@ -9,6 +9,7 @@ import (
"path"
"regexp"
"sort"
"strconv"
"strings"
"code.gitea.io/gitea/modules/base"
@ -378,6 +379,12 @@ func (issue *Issue) apiFormat(e Engine) *api.Issue {
Updated: issue.UpdatedUnix.AsTime(),
}
apiIssue.Repo = &api.RepositoryMeta{
ID: issue.Repo.ID,
Name: issue.Repo.Name,
FullName: issue.Repo.FullName(),
}
if issue.ClosedUnix != 0 {
apiIssue.Closed = issue.ClosedUnix.AsTimePtr()
}
@ -750,7 +757,6 @@ func (issue *Issue) UpdateAttachments(uuids []string) (err error) {
// ChangeContent changes issue content, as the given user.
func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
oldContent := issue.Content
issue.Content = content
sess := x.NewSession()
@ -769,47 +775,7 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
return err
}
if err = sess.Commit(); err != nil {
return err
}
sess.Close()
mode, _ := AccessLevel(issue.Poster, issue.Repo)
if issue.IsPull {
issue.PullRequest.Issue = issue
err = PrepareWebhooks(issue.Repo, HookEventPullRequest, &api.PullRequestPayload{
Action: api.HookIssueEdited,
Index: issue.Index,
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
PullRequest: issue.PullRequest.APIFormat(),
Repository: issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HookEventIssues, &api.IssuePayload{
Action: api.HookIssueEdited,
Index: issue.Index,
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
Issue: issue.APIFormat(),
Repository: issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go HookQueue.Add(issue.RepoID)
}
return nil
return sess.Commit()
}
// GetTasks returns the amount of tasks in the issues content
@ -1088,11 +1054,13 @@ type IssuesOptions struct {
LabelIDs []int64
SortType string
IssueIDs []int64
// prioritize issues from this repo
PriorityRepoID int64
}
// sortIssuesSession sort an issues-related session based on the provided
// sortType string
func sortIssuesSession(sess *xorm.Session, sortType string) {
func sortIssuesSession(sess *xorm.Session, sortType string, priorityRepoID int64) {
switch sortType {
case "oldest":
sess.Asc("issue.created_unix")
@ -1110,6 +1078,8 @@ func sortIssuesSession(sess *xorm.Session, sortType string) {
sess.Asc("issue.deadline_unix")
case "farduedate":
sess.Desc("issue.deadline_unix")
case "priorityrepo":
sess.OrderBy("CASE WHEN issue.repo_id = " + strconv.FormatInt(priorityRepoID, 10) + " THEN 1 ELSE 2 END, issue.created_unix DESC")
default:
sess.Desc("issue.created_unix")
}
@ -1211,7 +1181,7 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
defer sess.Close()
opts.setupSession(sess)
sortIssuesSession(sess, opts.SortType)
sortIssuesSession(sess, opts.SortType, opts.PriorityRepoID)
issues := make([]*Issue, 0, setting.UI.IssuePagingNum)
if err := sess.Find(&issues); err != nil {
@ -1517,8 +1487,8 @@ func GetRepoIssueStats(repoID, uid int64, filterMode int, isPull bool) (numOpen
}
// SearchIssueIDsByKeyword search issues on database
func SearchIssueIDsByKeyword(kw string, repoID int64, limit, start int) (int64, []int64, error) {
var repoCond = builder.Eq{"repo_id": repoID}
func SearchIssueIDsByKeyword(kw string, repoIDs []int64, limit, start int) (int64, []int64, error) {
var repoCond = builder.In("repo_id", repoIDs)
var subQuery = builder.Select("id").From("issue").Where(repoCond)
var cond = builder.And(
repoCond,
@ -1607,33 +1577,43 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *Us
return sess.Commit()
}
// DependencyInfo represents high level information about an issue which is a dependency of another issue.
type DependencyInfo struct {
Issue `xorm:"extends"`
Repository `xorm:"extends"`
}
// Get Blocked By Dependencies, aka all issues this issue is blocked by.
func (issue *Issue) getBlockedByDependencies(e Engine) (issueDeps []*Issue, err error) {
func (issue *Issue) getBlockedByDependencies(e Engine) (issueDeps []*DependencyInfo, err error) {
return issueDeps, e.
Table("issue_dependency").
Select("issue.*").
Join("INNER", "issue", "issue.id = issue_dependency.dependency_id").
Table("issue").
Join("INNER", "repository", "repository.id = issue.repo_id").
Join("INNER", "issue_dependency", "issue_dependency.dependency_id = issue.id").
Where("issue_id = ?", issue.ID).
//sort by repo id then created date, with the issues of the same repo at the beginning of the list
OrderBy("CASE WHEN issue.repo_id = " + strconv.FormatInt(issue.RepoID, 10) + " THEN 0 ELSE issue.repo_id END, issue.created_unix DESC").
Find(&issueDeps)
}
// Get Blocking Dependencies, aka all issues this issue blocks.
func (issue *Issue) getBlockingDependencies(e Engine) (issueDeps []*Issue, err error) {
func (issue *Issue) getBlockingDependencies(e Engine) (issueDeps []*DependencyInfo, err error) {
return issueDeps, e.
Table("issue_dependency").
Select("issue.*").
Join("INNER", "issue", "issue.id = issue_dependency.issue_id").
Table("issue").
Join("INNER", "repository", "repository.id = issue.repo_id").
Join("INNER", "issue_dependency", "issue_dependency.issue_id = issue.id").
Where("dependency_id = ?", issue.ID).
//sort by repo id then created date, with the issues of the same repo at the beginning of the list
OrderBy("CASE WHEN issue.repo_id = " + strconv.FormatInt(issue.RepoID, 10) + " THEN 0 ELSE issue.repo_id END, issue.created_unix DESC").
Find(&issueDeps)
}
// BlockedByDependencies finds all Dependencies an issue is blocked by
func (issue *Issue) BlockedByDependencies() ([]*Issue, error) {
func (issue *Issue) BlockedByDependencies() ([]*DependencyInfo, error) {
return issue.getBlockedByDependencies(x)
}
// BlockingDependencies returns all blocking dependencies, aka all other issues a given issue blocks
func (issue *Issue) BlockingDependencies() ([]*Issue, error) {
func (issue *Issue) BlockingDependencies() ([]*DependencyInfo, error) {
return issue.getBlockingDependencies(x)
}

View File

@ -444,6 +444,10 @@ func (c *Comment) LoadReview() error {
func (c *Comment) checkInvalidation(doer *User, repo *git.Repository, branch string) error {
// FIXME differentiate between previous and proposed line
commit, err := repo.LineBlame(branch, repo.Path, c.TreePath, uint(c.UnsignedLine()))
if err != nil && strings.Contains(err.Error(), "fatal: no such path") {
c.Invalidated = true
return UpdateComment(c, doer)
}
if err != nil {
return err
}

View File

@ -250,6 +250,19 @@ func GetLabelIDsInRepoByNames(repoID int64, labelNames []string) ([]int64, error
Find(&labelIDs)
}
// GetLabelIDsInReposByNames returns a list of labelIDs by names in one of the given
// repositories.
// it silently ignores label names that do not belong to the repository.
func GetLabelIDsInReposByNames(repoIDs []int64, labelNames []string) ([]int64, error) {
labelIDs := make([]int64, 0, len(labelNames))
return labelIDs, x.Table("label").
In("repo_id", repoIDs).
In("name", labelNames).
Asc("name").
Cols("id").
Find(&labelIDs)
}
// GetLabelInRepoByID returns a label by ID in given repository.
func GetLabelInRepoByID(repoID, labelID int64) (*Label, error) {
return getLabelInRepoByID(x, repoID, labelID)

View File

@ -264,24 +264,23 @@ func TestIssue_loadTotalTimes(t *testing.T) {
func TestIssue_SearchIssueIDsByKeyword(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
total, ids, err := SearchIssueIDsByKeyword("issue2", 1, 10, 0)
total, ids, err := SearchIssueIDsByKeyword("issue2", []int64{1}, 10, 0)
assert.NoError(t, err)
assert.EqualValues(t, 1, total)
assert.EqualValues(t, []int64{2}, ids)
total, ids, err = SearchIssueIDsByKeyword("first", 1, 10, 0)
total, ids, err = SearchIssueIDsByKeyword("first", []int64{1}, 10, 0)
assert.NoError(t, err)
assert.EqualValues(t, 1, total)
assert.EqualValues(t, []int64{1}, ids)
total, ids, err = SearchIssueIDsByKeyword("for", 1, 10, 0)
total, ids, err = SearchIssueIDsByKeyword("for", []int64{1}, 10, 0)
assert.NoError(t, err)
assert.EqualValues(t, 4, total)
assert.EqualValues(t, []int64{1, 2, 3, 5}, ids)
// issue1's comment id 2
total, ids, err = SearchIssueIDsByKeyword("good", 1, 10, 0)
total, ids, err = SearchIssueIDsByKeyword("good", []int64{1}, 10, 0)
assert.NoError(t, err)
assert.EqualValues(t, 1, total)
assert.EqualValues(t, []int64{1}, ids)

View File

@ -16,7 +16,6 @@ import (
"strings"
"time"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
@ -26,7 +25,6 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"github.com/unknwon/com"
"xorm.io/xorm"
)
var pullRequestQueue = sync.NewUniqueQueue(setting.Repository.PullRequestQueueLength)
@ -753,66 +751,6 @@ func newPullRequestAttempt(repo *Repository, pull *Issue, labelIDs []int64, uuid
return nil
}
// PullRequestsOptions holds the options for PRs
type PullRequestsOptions struct {
Page int
State string
SortType string
Labels []string
MilestoneID int64
}
func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xorm.Session, error) {
sess := x.Where("pull_request.base_repo_id=?", baseRepoID)
sess.Join("INNER", "issue", "pull_request.issue_id = issue.id")
switch opts.State {
case "closed", "open":
sess.And("issue.is_closed=?", opts.State == "closed")
}
if labelIDs, err := base.StringsToInt64s(opts.Labels); err != nil {
return nil, err
} else if len(labelIDs) > 0 {
sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id").
In("issue_label.label_id", labelIDs)
}
if opts.MilestoneID > 0 {
sess.And("issue.milestone_id=?", opts.MilestoneID)
}
return sess, nil
}
// PullRequests returns all pull requests for a base Repo by the given conditions
func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest, int64, error) {
if opts.Page <= 0 {
opts.Page = 1
}
countSession, err := listPullRequestStatement(baseRepoID, opts)
if err != nil {
log.Error("listPullRequestStatement: %v", err)
return nil, 0, err
}
maxResults, err := countSession.Count(new(PullRequest))
if err != nil {
log.Error("Count PRs: %v", err)
return nil, maxResults, err
}
prs := make([]*PullRequest, 0, ItemsPerPage)
findSession, err := listPullRequestStatement(baseRepoID, opts)
sortIssuesSession(findSession, opts.SortType)
if err != nil {
log.Error("listPullRequestStatement: %v", err)
return nil, maxResults, err
}
findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage)
return prs, maxResults, findSession.Find(&prs)
}
// GetUnmergedPullRequest returns a pull request that is open and has not been merged
// by given head/base and repo/branch.
func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch string) (*PullRequest, error) {
@ -831,17 +769,6 @@ func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch
return pr, nil
}
// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
// by given head information (repo and branch).
func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) {
prs := make([]*PullRequest, 0, 2)
return prs, x.
Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ?",
repoID, branch, false, false).
Join("INNER", "issue", "issue.id = pull_request.issue_id").
Find(&prs)
}
// GetLatestPullRequestByHeadInfo returns the latest pull request (regardless of its status)
// by given head information (repo and branch).
func GetLatestPullRequestByHeadInfo(repoID int64, branch string) (*PullRequest, error) {
@ -856,17 +783,6 @@ func GetLatestPullRequestByHeadInfo(repoID int64, branch string) (*PullRequest,
return pr, err
}
// GetUnmergedPullRequestsByBaseInfo returns all pull requests that are open and has not been merged
// by given base information (repo and branch).
func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequest, error) {
prs := make([]*PullRequest, 0, 2)
return prs, x.
Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?",
repoID, branch, false, false).
Join("INNER", "issue", "issue.id=pull_request.issue_id").
Find(&prs)
}
// GetPullRequestByIndex returns a pull request by the given index
func GetPullRequestByIndex(repoID int64, index int64) (*PullRequest, error) {
pr := &PullRequest{
@ -1035,72 +951,6 @@ func (pr *PullRequest) AddToTaskQueue() {
})
}
// PullRequestList defines a list of pull requests
type PullRequestList []*PullRequest
func (prs PullRequestList) loadAttributes(e Engine) error {
if len(prs) == 0 {
return nil
}
// Load issues.
issueIDs := prs.getIssueIDs()
issues := make([]*Issue, 0, len(issueIDs))
if err := e.
Where("id > 0").
In("id", issueIDs).
Find(&issues); err != nil {
return fmt.Errorf("find issues: %v", err)
}
set := make(map[int64]*Issue)
for i := range issues {
set[issues[i].ID] = issues[i]
}
for i := range prs {
prs[i].Issue = set[prs[i].IssueID]
}
return nil
}
func (prs PullRequestList) getIssueIDs() []int64 {
issueIDs := make([]int64, 0, len(prs))
for i := range prs {
issueIDs = append(issueIDs, prs[i].IssueID)
}
return issueIDs
}
// LoadAttributes load all the prs attributes
func (prs PullRequestList) LoadAttributes() error {
return prs.loadAttributes(x)
}
func (prs PullRequestList) invalidateCodeComments(e Engine, doer *User, repo *git.Repository, branch string) error {
if len(prs) == 0 {
return nil
}
issueIDs := prs.getIssueIDs()
var codeComments []*Comment
if err := e.
Where("type = ? and invalidated = ?", CommentTypeCode, false).
In("issue_id", issueIDs).
Find(&codeComments); err != nil {
return fmt.Errorf("find code comments: %v", err)
}
for _, comment := range codeComments {
if err := comment.CheckInvalidation(repo, doer, branch); err != nil {
return err
}
}
return nil
}
// InvalidateCodeComments will lookup the prs for code comments which got invalidated by change
func (prs PullRequestList) InvalidateCodeComments(doer *User, repo *git.Repository, branch string) error {
return prs.invalidateCodeComments(x, doer, repo, branch)
}
// checkAndUpdateStatus checks if pull request is possible to leaving checking status,
// and set to be either conflict or mergeable.
func (pr *PullRequest) checkAndUpdateStatus() {
@ -1152,64 +1002,3 @@ func (pr *PullRequest) GetWorkInProgressPrefix() string {
}
return ""
}
// TestPullRequests checks and tests untested patches of pull requests.
// TODO: test more pull requests at same time.
func TestPullRequests() {
prs := make([]*PullRequest, 0, 10)
err := x.Where("status = ?", PullRequestStatusChecking).Find(&prs)
if err != nil {
log.Error("Find Checking PRs: %v", err)
return
}
var checkedPRs = make(map[int64]struct{})
// Update pull request status.
for _, pr := range prs {
checkedPRs[pr.ID] = struct{}{}
if err := pr.GetBaseRepo(); err != nil {
log.Error("GetBaseRepo: %v", err)
continue
}
if pr.manuallyMerged() {
continue
}
if err := pr.testPatch(x); err != nil {
log.Error("testPatch: %v", err)
continue
}
pr.checkAndUpdateStatus()
}
// Start listening on new test requests.
for prID := range pullRequestQueue.Queue() {
log.Trace("TestPullRequests[%v]: processing test task", prID)
pullRequestQueue.Remove(prID)
id := com.StrTo(prID).MustInt64()
if _, ok := checkedPRs[id]; ok {
continue
}
pr, err := GetPullRequestByID(id)
if err != nil {
log.Error("GetPullRequestByID[%s]: %v", prID, err)
continue
} else if pr.manuallyMerged() {
continue
} else if err = pr.testPatch(x); err != nil {
log.Error("testPatch[%d]: %v", pr.ID, err)
continue
}
pr.checkAndUpdateStatus()
}
}
// InitTestPullRequests runs the task to test all the checking status pull requests
func InitTestPullRequests() {
go TestPullRequests()
}

224
models/pull_list.go Normal file
View File

@ -0,0 +1,224 @@
// Copyright 2019 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/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"github.com/unknwon/com"
"xorm.io/xorm"
)
// PullRequestsOptions holds the options for PRs
type PullRequestsOptions struct {
Page int
State string
SortType string
Labels []string
MilestoneID int64
}
func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xorm.Session, error) {
sess := x.Where("pull_request.base_repo_id=?", baseRepoID)
sess.Join("INNER", "issue", "pull_request.issue_id = issue.id")
switch opts.State {
case "closed", "open":
sess.And("issue.is_closed=?", opts.State == "closed")
}
if labelIDs, err := base.StringsToInt64s(opts.Labels); err != nil {
return nil, err
} else if len(labelIDs) > 0 {
sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id").
In("issue_label.label_id", labelIDs)
}
if opts.MilestoneID > 0 {
sess.And("issue.milestone_id=?", opts.MilestoneID)
}
return sess, nil
}
// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
// by given head information (repo and branch).
func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) {
prs := make([]*PullRequest, 0, 2)
return prs, x.
Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ?",
repoID, branch, false, false).
Join("INNER", "issue", "issue.id = pull_request.issue_id").
Find(&prs)
}
// GetUnmergedPullRequestsByBaseInfo returns all pull requests that are open and has not been merged
// by given base information (repo and branch).
func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequest, error) {
prs := make([]*PullRequest, 0, 2)
return prs, x.
Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?",
repoID, branch, false, false).
Join("INNER", "issue", "issue.id=pull_request.issue_id").
Find(&prs)
}
// PullRequests returns all pull requests for a base Repo by the given conditions
func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest, int64, error) {
if opts.Page <= 0 {
opts.Page = 1
}
countSession, err := listPullRequestStatement(baseRepoID, opts)
if err != nil {
log.Error("listPullRequestStatement: %v", err)
return nil, 0, err
}
maxResults, err := countSession.Count(new(PullRequest))
if err != nil {
log.Error("Count PRs: %v", err)
return nil, maxResults, err
}
prs := make([]*PullRequest, 0, ItemsPerPage)
findSession, err := listPullRequestStatement(baseRepoID, opts)
sortIssuesSession(findSession, opts.SortType, 0)
if err != nil {
log.Error("listPullRequestStatement: %v", err)
return nil, maxResults, err
}
findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage)
return prs, maxResults, findSession.Find(&prs)
}
// PullRequestList defines a list of pull requests
type PullRequestList []*PullRequest
func (prs PullRequestList) loadAttributes(e Engine) error {
if len(prs) == 0 {
return nil
}
// Load issues.
issueIDs := prs.getIssueIDs()
issues := make([]*Issue, 0, len(issueIDs))
if err := e.
Where("id > 0").
In("id", issueIDs).
Find(&issues); err != nil {
return fmt.Errorf("find issues: %v", err)
}
set := make(map[int64]*Issue)
for i := range issues {
set[issues[i].ID] = issues[i]
}
for i := range prs {
prs[i].Issue = set[prs[i].IssueID]
}
return nil
}
func (prs PullRequestList) getIssueIDs() []int64 {
issueIDs := make([]int64, 0, len(prs))
for i := range prs {
issueIDs = append(issueIDs, prs[i].IssueID)
}
return issueIDs
}
// LoadAttributes load all the prs attributes
func (prs PullRequestList) LoadAttributes() error {
return prs.loadAttributes(x)
}
func (prs PullRequestList) invalidateCodeComments(e Engine, doer *User, repo *git.Repository, branch string) error {
if len(prs) == 0 {
return nil
}
issueIDs := prs.getIssueIDs()
var codeComments []*Comment
if err := e.
Where("type = ? and invalidated = ?", CommentTypeCode, false).
In("issue_id", issueIDs).
Find(&codeComments); err != nil {
return fmt.Errorf("find code comments: %v", err)
}
for _, comment := range codeComments {
if err := comment.CheckInvalidation(repo, doer, branch); err != nil {
return err
}
}
return nil
}
// InvalidateCodeComments will lookup the prs for code comments which got invalidated by change
func (prs PullRequestList) InvalidateCodeComments(doer *User, repo *git.Repository, branch string) error {
return prs.invalidateCodeComments(x, doer, repo, branch)
}
// TestPullRequests checks and tests untested patches of pull requests.
// TODO: test more pull requests at same time.
func TestPullRequests() {
prs := make([]*PullRequest, 0, 10)
err := x.Where("status = ?", PullRequestStatusChecking).Find(&prs)
if err != nil {
log.Error("Find Checking PRs: %v", err)
return
}
var checkedPRs = make(map[int64]struct{})
// Update pull request status.
for _, pr := range prs {
checkedPRs[pr.ID] = struct{}{}
if err := pr.GetBaseRepo(); err != nil {
log.Error("GetBaseRepo: %v", err)
continue
}
if pr.manuallyMerged() {
continue
}
if err := pr.testPatch(x); err != nil {
log.Error("testPatch: %v", err)
continue
}
pr.checkAndUpdateStatus()
}
// Start listening on new test requests.
for prID := range pullRequestQueue.Queue() {
log.Trace("TestPullRequests[%v]: processing test task", prID)
pullRequestQueue.Remove(prID)
id := com.StrTo(prID).MustInt64()
if _, ok := checkedPRs[id]; ok {
continue
}
pr, err := GetPullRequestByID(id)
if err != nil {
log.Error("GetPullRequestByID[%s]: %v", prID, err)
continue
} else if pr.manuallyMerged() {
continue
} else if err = pr.testPatch(x); err != nil {
log.Error("testPatch[%d]: %v", pr.ID, err)
continue
}
pr.checkAndUpdateStatus()
}
}
// InitTestPullRequests runs the task to test all the checking status pull requests
func InitTestPullRequests() {
go TestPullRequests()
}

View File

@ -218,9 +218,18 @@ func (b *BleveIndexer) Delete(ids ...int64) error {
// Search searches for issues by given conditions.
// Returns the matching issue IDs
func (b *BleveIndexer) Search(keyword string, repoID int64, limit, start int) (*SearchResult, error) {
func (b *BleveIndexer) Search(keyword string, repoIDs []int64, limit, start int) (*SearchResult, error) {
var repoQueriesP []*query.NumericRangeQuery
for _, repoID := range repoIDs {
repoQueriesP = append(repoQueriesP, numericEqualityQuery(repoID, "RepoID"))
}
repoQueries := make([]query.Query, len(repoQueriesP))
for i, v := range repoQueriesP {
repoQueries[i] = query.Query(v)
}
indexerQuery := bleve.NewConjunctionQuery(
numericEqualityQuery(repoID, "RepoID"),
bleve.NewDisjunctionQuery(repoQueries...),
bleve.NewDisjunctionQuery(
newMatchPhraseQuery(keyword, "Title", issueIndexerAnalyzer),
newMatchPhraseQuery(keyword, "Content", issueIndexerAnalyzer),
@ -242,8 +251,7 @@ func (b *BleveIndexer) Search(keyword string, repoID int64, limit, start int) (*
return nil, err
}
ret.Hits = append(ret.Hits, Match{
ID: id,
RepoID: repoID,
ID: id,
})
}
return &ret, nil

View File

@ -76,7 +76,7 @@ func TestBleveIndexAndSearch(t *testing.T) {
)
for _, kw := range keywords {
res, err := indexer.Search(kw.Keyword, 2, 10, 0)
res, err := indexer.Search(kw.Keyword, []int64{2}, 10, 0)
assert.NoError(t, err)
var ids = make([]int64, 0, len(res.Hits))

View File

@ -26,8 +26,8 @@ func (db *DBIndexer) Delete(ids ...int64) error {
}
// Search dummy function
func (db *DBIndexer) Search(kw string, repoID int64, limit, start int) (*SearchResult, error) {
total, ids, err := models.SearchIssueIDsByKeyword(kw, repoID, limit, start)
func (db *DBIndexer) Search(kw string, repoIDs []int64, limit, start int) (*SearchResult, error) {
total, ids, err := models.SearchIssueIDsByKeyword(kw, repoIDs, limit, start)
if err != nil {
return nil, err
}
@ -37,8 +37,7 @@ func (db *DBIndexer) Search(kw string, repoID int64, limit, start int) (*SearchR
}
for _, id := range ids {
result.Hits = append(result.Hits, Match{
ID: id,
RepoID: repoID,
ID: id,
})
}
return &result, nil

View File

@ -28,9 +28,8 @@ type IndexerData struct {
// Match represents on search result
type Match struct {
ID int64 `json:"id"`
RepoID int64 `json:"repo_id"`
Score float64 `json:"score"`
ID int64 `json:"id"`
Score float64 `json:"score"`
}
// SearchResult represents search results
@ -44,7 +43,7 @@ type Indexer interface {
Init() (bool, error)
Index(issue []*IndexerData) error
Delete(ids ...int64) error
Search(kw string, repoID int64, limit, start int) (*SearchResult, error)
Search(kw string, repoIDs []int64, limit, start int) (*SearchResult, error)
}
type indexerHolder struct {
@ -262,9 +261,9 @@ func DeleteRepoIssueIndexer(repo *models.Repository) {
}
// SearchIssuesByKeyword search issue ids by keywords and repo id
func SearchIssuesByKeyword(repoID int64, keyword string) ([]int64, error) {
func SearchIssuesByKeyword(repoIDs []int64, keyword string) ([]int64, error) {
var issueIDs []int64
res, err := holder.get().Search(keyword, repoID, 1000, 0)
res, err := holder.get().Search(keyword, repoIDs, 1000, 0)
if err != nil {
return nil, err
}

View File

@ -30,19 +30,19 @@ func TestBleveSearchIssues(t *testing.T) {
time.Sleep(5 * time.Second)
ids, err := SearchIssuesByKeyword(1, "issue2")
ids, err := SearchIssuesByKeyword([]int64{1}, "issue2")
assert.NoError(t, err)
assert.EqualValues(t, []int64{2}, ids)
ids, err = SearchIssuesByKeyword(1, "first")
ids, err = SearchIssuesByKeyword([]int64{1}, "first")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
ids, err = SearchIssuesByKeyword(1, "for")
ids, err = SearchIssuesByKeyword([]int64{1}, "for")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1, 2, 3, 5}, ids)
ids, err = SearchIssuesByKeyword(1, "good")
ids, err = SearchIssuesByKeyword([]int64{1}, "good")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
}
@ -53,19 +53,19 @@ func TestDBSearchIssues(t *testing.T) {
setting.Indexer.IssueType = "db"
InitIssueIndexer(true)
ids, err := SearchIssuesByKeyword(1, "issue2")
ids, err := SearchIssuesByKeyword([]int64{1}, "issue2")
assert.NoError(t, err)
assert.EqualValues(t, []int64{2}, ids)
ids, err = SearchIssuesByKeyword(1, "first")
ids, err = SearchIssuesByKeyword([]int64{1}, "first")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
ids, err = SearchIssuesByKeyword(1, "for")
ids, err = SearchIssuesByKeyword([]int64{1}, "for")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1, 2, 3, 5}, ids)
ids, err = SearchIssuesByKeyword(1, "good")
ids, err = SearchIssuesByKeyword([]int64{1}, "good")
assert.NoError(t, err)
assert.EqualValues(t, []int64{1}, ids)
}

View File

@ -323,6 +323,6 @@ func TestRender_ShortLinks(t *testing.T) {
`<p><a href="`+notencodedImgurlWiki+`" rel="nofollow"><img src="`+notencodedImgurlWiki+`"/></a></p>`)
test(
"<p><a href=\"https://example.org\">[[foobar]]</a></p>",
`<p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p>`,
`<p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p>`)
`<p></p><p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p><p></p>`,
`<p></p><p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p><p></p>`)
}

View File

@ -7,13 +7,14 @@ package markdown
import (
"bytes"
"io"
"strings"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"github.com/russross/blackfriday"
"github.com/russross/blackfriday/v2"
)
// Renderer is a extended version of underlying render object.
@ -25,134 +26,138 @@ type Renderer struct {
var byteMailto = []byte("mailto:")
// Link defines how formal links should be processed to produce corresponding HTML elements.
func (r *Renderer) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
// special case: this is not a link, a hash link or a mailto:, so it's a
// relative URL
if len(link) > 0 && !markup.IsLink(link) &&
link[0] != '#' && !bytes.HasPrefix(link, byteMailto) {
lnk := string(link)
var htmlEscaper = [256][]byte{
'&': []byte("&amp;"),
'<': []byte("&lt;"),
'>': []byte("&gt;"),
'"': []byte("&quot;"),
}
func escapeHTML(w io.Writer, s []byte) {
var start, end int
for end < len(s) {
escSeq := htmlEscaper[s[end]]
if escSeq != nil {
_, _ = w.Write(s[start:end])
_, _ = w.Write(escSeq)
start = end + 1
}
end++
}
if start < len(s) && end <= len(s) {
_, _ = w.Write(s[start:end])
}
}
// RenderNode is a default renderer of a single node of a syntax tree. For
// block nodes it will be called twice: first time with entering=true, second
// time with entering=false, so that it could know when it's working on an open
// tag and when on close. It writes the result to w.
//
// The return value is a way to tell the calling walker to adjust its walk
// pattern: e.g. it can terminate the traversal by returning Terminate. Or it
// can ask the walker to skip a subtree of this node by returning SkipChildren.
// The typical behavior is to return GoToNext, which asks for the usual
// traversal to the next node.
func (r *Renderer) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus {
switch node.Type {
case blackfriday.Image:
prefix := r.URLPrefix
if r.IsWiki {
lnk = util.URLJoin("wiki", lnk)
prefix = util.URLJoin(prefix, "wiki", "raw")
}
mLink := util.URLJoin(r.URLPrefix, lnk)
link = []byte(mLink)
}
if len(content) > 10 && string(content[0:9]) == "<a href=\"" && bytes.Contains(content[9:], []byte("<img")) {
// Image with link case: markdown `[![]()]()`
// If the content is an image, then we change the original href around it
// which points to itself to a new address "link"
rightQuote := bytes.Index(content[9:], []byte("\""))
content = bytes.Replace(content, content[9:9+rightQuote], link, 1)
out.Write(content)
} else {
r.Renderer.Link(out, link, title, content)
}
}
// List renders markdown bullet or digit lists to HTML
func (r *Renderer) List(out *bytes.Buffer, text func() bool, flags int) {
marker := out.Len()
if out.Len() > 0 {
out.WriteByte('\n')
}
if flags&blackfriday.LIST_TYPE_DEFINITION != 0 {
out.WriteString("<dl>")
} else if flags&blackfriday.LIST_TYPE_ORDERED != 0 {
out.WriteString("<ol class='ui list'>")
} else {
out.WriteString("<ul class='ui list'>")
}
if !text() {
out.Truncate(marker)
return
}
if flags&blackfriday.LIST_TYPE_DEFINITION != 0 {
out.WriteString("</dl>\n")
} else if flags&blackfriday.LIST_TYPE_ORDERED != 0 {
out.WriteString("</ol>\n")
} else {
out.WriteString("</ul>\n")
}
}
// ListItem defines how list items should be processed to produce corresponding HTML elements.
func (r *Renderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
// Detect procedures to draw checkboxes.
prefix := ""
if bytes.HasPrefix(text, []byte("<p>")) {
prefix = "<p>"
}
switch {
case bytes.HasPrefix(text, []byte(prefix+"[ ] ")):
text = append([]byte(`<span class="ui fitted disabled checkbox"><input type="checkbox" disabled="disabled" /><label /></span>`), text[3+len(prefix):]...)
if prefix != "" {
text = bytes.Replace(text, []byte(prefix), []byte{}, 1)
prefix = strings.Replace(prefix, "/src/", "/media/", 1)
link := node.LinkData.Destination
if len(link) > 0 && !markup.IsLink(link) {
lnk := string(link)
lnk = util.URLJoin(prefix, lnk)
lnk = strings.Replace(lnk, " ", "+", -1)
link = []byte(lnk)
}
case bytes.HasPrefix(text, []byte(prefix+"[x] ")):
text = append([]byte(`<span class="ui checked fitted disabled checkbox"><input type="checkbox" checked="" disabled="disabled" /><label /></span>`), text[3+len(prefix):]...)
if prefix != "" {
text = bytes.Replace(text, []byte(prefix), []byte{}, 1)
node.LinkData.Destination = link
// Render link around image only if parent is not link already
if node.Parent != nil && node.Parent.Type != blackfriday.Link {
if entering {
_, _ = w.Write([]byte(`<a href="`))
escapeHTML(w, link)
_, _ = w.Write([]byte(`">`))
return r.Renderer.RenderNode(w, node, entering)
}
s := r.Renderer.RenderNode(w, node, entering)
_, _ = w.Write([]byte(`</a>`))
return s
}
return r.Renderer.RenderNode(w, node, entering)
case blackfriday.Link:
// special case: this is not a link, a hash link or a mailto:, so it's a
// relative URL
link := node.LinkData.Destination
if len(link) > 0 && !markup.IsLink(link) &&
link[0] != '#' && !bytes.HasPrefix(link, byteMailto) &&
node.LinkData.Footnote == nil {
lnk := string(link)
if r.IsWiki {
lnk = util.URLJoin("wiki", lnk)
}
link = []byte(util.URLJoin(r.URLPrefix, lnk))
}
node.LinkData.Destination = link
return r.Renderer.RenderNode(w, node, entering)
case blackfriday.Text:
isListItem := false
for n := node.Parent; n != nil; n = n.Parent {
if n.Type == blackfriday.Item {
isListItem = true
break
}
}
if isListItem {
text := node.Literal
switch {
case bytes.HasPrefix(text, []byte("[ ] ")):
_, _ = w.Write([]byte(`<span class="ui fitted disabled checkbox"><input type="checkbox" disabled="disabled" /><label /></span>`))
text = text[3:]
case bytes.HasPrefix(text, []byte("[x] ")):
_, _ = w.Write([]byte(`<span class="ui checked fitted disabled checkbox"><input type="checkbox" checked="" disabled="disabled" /><label /></span>`))
text = text[3:]
}
node.Literal = text
}
}
r.Renderer.ListItem(out, text, flags)
}
// Image defines how images should be processed to produce corresponding HTML elements.
func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
prefix := r.URLPrefix
if r.IsWiki {
prefix = util.URLJoin(prefix, "wiki", "raw")
}
prefix = strings.Replace(prefix, "/src/", "/media/", 1)
if len(link) > 0 && !markup.IsLink(link) {
lnk := string(link)
lnk = util.URLJoin(prefix, lnk)
lnk = strings.Replace(lnk, " ", "+", -1)
link = []byte(lnk)
}
// Put a link around it pointing to itself by default
out.WriteString(`<a href="`)
out.Write(link)
out.WriteString(`">`)
r.Renderer.Image(out, link, title, alt)
out.WriteString("</a>")
return r.Renderer.RenderNode(w, node, entering)
}
const (
blackfridayExtensions = 0 |
blackfriday.EXTENSION_NO_INTRA_EMPHASIS |
blackfriday.EXTENSION_TABLES |
blackfriday.EXTENSION_FENCED_CODE |
blackfriday.EXTENSION_STRIKETHROUGH |
blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK |
blackfriday.EXTENSION_DEFINITION_LISTS |
blackfriday.EXTENSION_FOOTNOTES |
blackfriday.EXTENSION_HEADER_IDS |
blackfriday.EXTENSION_AUTO_HEADER_IDS
blackfriday.NoIntraEmphasis |
blackfriday.Tables |
blackfriday.FencedCode |
blackfriday.Strikethrough |
blackfriday.NoEmptyLineBeforeBlock |
blackfriday.DefinitionLists |
blackfriday.Footnotes |
blackfriday.HeadingIDs |
blackfriday.AutoHeadingIDs
blackfridayHTMLFlags = 0 |
blackfriday.HTML_SKIP_STYLE |
blackfriday.HTML_OMIT_CONTENTS |
blackfriday.HTML_USE_SMARTYPANTS
blackfriday.Smartypants
)
// RenderRaw renders Markdown to HTML without handling special links.
func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
renderer := &Renderer{
Renderer: blackfriday.HtmlRenderer(blackfridayHTMLFlags, "", ""),
Renderer: blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{
Flags: blackfridayHTMLFlags,
}),
URLPrefix: urlPrefix,
IsWiki: wikiMarkdown,
}
exts := blackfridayExtensions
if setting.Markdown.EnableHardLineBreak {
exts |= blackfriday.EXTENSION_HARD_LINE_BREAK
exts |= blackfriday.HardLineBreak
}
body = blackfriday.Markdown(body, renderer, exts)
body = blackfriday.Run(body, blackfriday.WithRenderer(renderer), blackfriday.WithExtensions(exts))
return markup.SanitizeBytes(body)
}

View File

@ -166,13 +166,13 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
<h3 id="footnotes">Footnotes</h3>
<p>Here is a simple footnote,<sup id="fnref:1"><a href="#fn:1" rel="nofollow">1</a></sup> and here is a longer one.<sup id="fnref:bignote"><a href="#fn:bignote" rel="nofollow">2</a></sup></p>
<div>
<hr/>
<ol>
<li id="fn:1">This is the first footnote.
</li>
<li id="fn:1">This is the first footnote.</li>
<li id="fn:bignote"><p>Here is one with multiple paragraphs and code.</p>
@ -180,9 +180,9 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
<p><code>{ my code }</code></p>
<p>Add as many paragraphs as you like.</p>
</li>
<p>Add as many paragraphs as you like.</p></li>
</ol>
</div>
`,
}

View File

@ -6,43 +6,39 @@ package mdstripper
import (
"bytes"
"io"
"github.com/russross/blackfriday"
"github.com/russross/blackfriday/v2"
)
// MarkdownStripper extends blackfriday.Renderer
type MarkdownStripper struct {
blackfriday.Renderer
links []string
coallesce bool
empty bool
}
const (
blackfridayExtensions = 0 |
blackfriday.EXTENSION_NO_INTRA_EMPHASIS |
blackfriday.EXTENSION_TABLES |
blackfriday.EXTENSION_FENCED_CODE |
blackfriday.EXTENSION_STRIKETHROUGH |
blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK |
blackfriday.EXTENSION_DEFINITION_LISTS |
blackfriday.EXTENSION_FOOTNOTES |
blackfriday.EXTENSION_HEADER_IDS |
blackfriday.EXTENSION_AUTO_HEADER_IDS |
blackfriday.NoIntraEmphasis |
blackfriday.Tables |
blackfriday.FencedCode |
blackfriday.Strikethrough |
blackfriday.NoEmptyLineBeforeBlock |
blackfriday.DefinitionLists |
blackfriday.Footnotes |
blackfriday.HeadingIDs |
blackfriday.AutoHeadingIDs |
// Not included in modules/markup/markdown/markdown.go;
// required here to process inline links
blackfriday.EXTENSION_AUTOLINK
blackfriday.Autolink
)
//revive:disable:var-naming Implementing the Rendering interface requires breaking some linting rules
// StripMarkdown parses markdown content by removing all markup and code blocks
// in order to extract links and other references
func StripMarkdown(rawBytes []byte) (string, []string) {
stripper := &MarkdownStripper{
links: make([]string, 0, 10),
}
body := blackfriday.Markdown(rawBytes, stripper, blackfridayExtensions)
return string(body), stripper.GetLinks()
buf, links := StripMarkdownBytes(rawBytes)
return string(buf), links
}
// StripMarkdownBytes parses markdown content by removing all markup and code blocks
@ -50,205 +46,67 @@ func StripMarkdown(rawBytes []byte) (string, []string) {
func StripMarkdownBytes(rawBytes []byte) ([]byte, []string) {
stripper := &MarkdownStripper{
links: make([]string, 0, 10),
empty: true,
}
body := blackfriday.Markdown(rawBytes, stripper, blackfridayExtensions)
return body, stripper.GetLinks()
parser := blackfriday.New(blackfriday.WithRenderer(stripper), blackfriday.WithExtensions(blackfridayExtensions))
ast := parser.Parse(rawBytes)
var buf bytes.Buffer
stripper.RenderHeader(&buf, ast)
ast.Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus {
return stripper.RenderNode(&buf, node, entering)
})
stripper.RenderFooter(&buf, ast)
return buf.Bytes(), stripper.GetLinks()
}
// block-level callbacks
// BlockCode dummy function to proceed with rendering
func (r *MarkdownStripper) BlockCode(out *bytes.Buffer, text []byte, infoString string) {
// Not rendered
// RenderNode is the main rendering method. It will be called once for
// every leaf node and twice for every non-leaf node (first with
// entering=true, then with entering=false). The method should write its
// rendition of the node to the supplied writer w.
func (r *MarkdownStripper) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus {
if !entering {
return blackfriday.GoToNext
}
switch node.Type {
case blackfriday.Text:
r.processString(w, node.Literal, node.Parent == nil)
return blackfriday.GoToNext
case blackfriday.Link:
r.processLink(w, node.LinkData.Destination)
r.coallesce = false
return blackfriday.SkipChildren
}
r.coallesce = false
return blackfriday.GoToNext
}
// BlockQuote dummy function to proceed with rendering
func (r *MarkdownStripper) BlockQuote(out *bytes.Buffer, text []byte) {
// FIXME: perhaps it's better to leave out block quote for this?
r.processString(out, text, false)
// RenderHeader is a method that allows the renderer to produce some
// content preceding the main body of the output document.
func (r *MarkdownStripper) RenderHeader(w io.Writer, ast *blackfriday.Node) {
}
// BlockHtml dummy function to proceed with rendering
func (r *MarkdownStripper) BlockHtml(out *bytes.Buffer, text []byte) { //nolint
// Not rendered
r.coallesce = false
// RenderFooter is a symmetric counterpart of RenderHeader.
func (r *MarkdownStripper) RenderFooter(w io.Writer, ast *blackfriday.Node) {
}
// Header dummy function to proceed with rendering
func (r *MarkdownStripper) Header(out *bytes.Buffer, text func() bool, level int, id string) {
text()
r.coallesce = false
}
// HRule dummy function to proceed with rendering
func (r *MarkdownStripper) HRule(out *bytes.Buffer) {
// Not rendered
r.coallesce = false
}
// List dummy function to proceed with rendering
func (r *MarkdownStripper) List(out *bytes.Buffer, text func() bool, flags int) {
text()
r.coallesce = false
}
// ListItem dummy function to proceed with rendering
func (r *MarkdownStripper) ListItem(out *bytes.Buffer, text []byte, flags int) {
r.processString(out, text, false)
}
// Paragraph dummy function to proceed with rendering
func (r *MarkdownStripper) Paragraph(out *bytes.Buffer, text func() bool) {
text()
r.coallesce = false
}
// Table dummy function to proceed with rendering
func (r *MarkdownStripper) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {
r.processString(out, header, false)
r.processString(out, body, false)
}
// TableRow dummy function to proceed with rendering
func (r *MarkdownStripper) TableRow(out *bytes.Buffer, text []byte) {
r.processString(out, text, false)
}
// TableHeaderCell dummy function to proceed with rendering
func (r *MarkdownStripper) TableHeaderCell(out *bytes.Buffer, text []byte, flags int) {
r.processString(out, text, false)
}
// TableCell dummy function to proceed with rendering
func (r *MarkdownStripper) TableCell(out *bytes.Buffer, text []byte, flags int) {
r.processString(out, text, false)
}
// Footnotes dummy function to proceed with rendering
func (r *MarkdownStripper) Footnotes(out *bytes.Buffer, text func() bool) {
text()
}
// FootnoteItem dummy function to proceed with rendering
func (r *MarkdownStripper) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) {
r.processString(out, text, false)
}
// TitleBlock dummy function to proceed with rendering
func (r *MarkdownStripper) TitleBlock(out *bytes.Buffer, text []byte) {
r.processString(out, text, false)
}
// Span-level callbacks
// AutoLink dummy function to proceed with rendering
func (r *MarkdownStripper) AutoLink(out *bytes.Buffer, link []byte, kind int) {
r.processLink(out, link, []byte{})
}
// CodeSpan dummy function to proceed with rendering
func (r *MarkdownStripper) CodeSpan(out *bytes.Buffer, text []byte) {
// Not rendered
r.coallesce = false
}
// DoubleEmphasis dummy function to proceed with rendering
func (r *MarkdownStripper) DoubleEmphasis(out *bytes.Buffer, text []byte) {
r.processString(out, text, false)
}
// Emphasis dummy function to proceed with rendering
func (r *MarkdownStripper) Emphasis(out *bytes.Buffer, text []byte) {
r.processString(out, text, false)
}
// Image dummy function to proceed with rendering
func (r *MarkdownStripper) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
// Not rendered
r.coallesce = false
}
// LineBreak dummy function to proceed with rendering
func (r *MarkdownStripper) LineBreak(out *bytes.Buffer) {
// Not rendered
r.coallesce = false
}
// Link dummy function to proceed with rendering
func (r *MarkdownStripper) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
r.processLink(out, link, content)
}
// RawHtmlTag dummy function to proceed with rendering
func (r *MarkdownStripper) RawHtmlTag(out *bytes.Buffer, tag []byte) { //nolint
// Not rendered
r.coallesce = false
}
// TripleEmphasis dummy function to proceed with rendering
func (r *MarkdownStripper) TripleEmphasis(out *bytes.Buffer, text []byte) {
r.processString(out, text, false)
}
// StrikeThrough dummy function to proceed with rendering
func (r *MarkdownStripper) StrikeThrough(out *bytes.Buffer, text []byte) {
r.processString(out, text, false)
}
// FootnoteRef dummy function to proceed with rendering
func (r *MarkdownStripper) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {
// Not rendered
r.coallesce = false
}
// Low-level callbacks
// Entity dummy function to proceed with rendering
func (r *MarkdownStripper) Entity(out *bytes.Buffer, entity []byte) {
// FIXME: literal entities are not parsed; perhaps they should
r.coallesce = false
}
// NormalText dummy function to proceed with rendering
func (r *MarkdownStripper) NormalText(out *bytes.Buffer, text []byte) {
r.processString(out, text, true)
}
// Header and footer
// DocumentHeader dummy function to proceed with rendering
func (r *MarkdownStripper) DocumentHeader(out *bytes.Buffer) {
r.coallesce = false
}
// DocumentFooter dummy function to proceed with rendering
func (r *MarkdownStripper) DocumentFooter(out *bytes.Buffer) {
r.coallesce = false
}
// GetFlags returns rendering flags
func (r *MarkdownStripper) GetFlags() int {
return 0
}
//revive:enable:var-naming
func doubleSpace(out *bytes.Buffer) {
if out.Len() > 0 {
out.WriteByte('\n')
func (r *MarkdownStripper) doubleSpace(w io.Writer) {
if !r.empty {
_, _ = w.Write([]byte{'\n'})
}
}
func (r *MarkdownStripper) processString(out *bytes.Buffer, text []byte, coallesce bool) {
func (r *MarkdownStripper) processString(w io.Writer, text []byte, coallesce bool) {
// Always break-up words
if !coallesce || !r.coallesce {
doubleSpace(out)
r.doubleSpace(w)
}
out.Write(text)
_, _ = w.Write(text)
r.coallesce = coallesce
r.empty = false
}
func (r *MarkdownStripper) processLink(out *bytes.Buffer, link []byte, content []byte) {
func (r *MarkdownStripper) processLink(w io.Writer, link []byte) {
// Links are processed out of band
r.links = append(r.links, string(link))
r.coallesce = false

View File

@ -5,12 +5,16 @@
package markup
import (
"bytes"
"fmt"
"html"
"strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/util"
"github.com/chaseadamsio/goorgeous"
"github.com/russross/blackfriday"
"github.com/niklasfasching/go-org/org"
)
func init() {
@ -32,23 +36,23 @@ func (Parser) Extensions() []string {
}
// Render renders orgmode rawbytes to HTML
func Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) (result []byte) {
defer func() {
if err := recover(); err != nil {
log.Error("Panic in orgmode.Render: %v Just returning the rawBytes", err)
result = rawBytes
}
}()
htmlFlags := blackfriday.HTML_USE_XHTML
htmlFlags |= blackfriday.HTML_SKIP_STYLE
htmlFlags |= blackfriday.HTML_OMIT_CONTENTS
renderer := &markdown.Renderer{
Renderer: blackfriday.HtmlRenderer(htmlFlags, "", ""),
URLPrefix: urlPrefix,
IsWiki: isWiki,
func Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte {
htmlWriter := org.NewHTMLWriter()
renderer := &Renderer{
HTMLWriter: htmlWriter,
URLPrefix: urlPrefix,
IsWiki: isWiki,
}
result = goorgeous.Org(rawBytes, renderer)
return
htmlWriter.ExtendingWriter = renderer
res, err := org.New().Silent().Parse(bytes.NewReader(rawBytes), "").Write(renderer)
if err != nil {
log.Error("Panic in orgmode.Render: %v Just returning the rawBytes", err)
return rawBytes
}
return []byte(res)
}
// RenderString reners orgmode string to HTML string
@ -56,7 +60,63 @@ func RenderString(rawContent string, urlPrefix string, metas map[string]string,
return string(Render([]byte(rawContent), urlPrefix, metas, isWiki))
}
// Render implements markup.Parser
// Render reners orgmode string to HTML string
func (Parser) Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte {
return Render(rawBytes, urlPrefix, metas, isWiki)
}
// Renderer implements org.Writer
type Renderer struct {
*org.HTMLWriter
URLPrefix string
IsWiki bool
}
var byteMailto = []byte("mailto:")
// WriteRegularLink renders images, links or videos
func (r *Renderer) WriteRegularLink(l org.RegularLink) {
link := []byte(html.EscapeString(l.URL))
if l.Protocol == "file" {
link = link[len("file:"):]
}
if len(link) > 0 && !markup.IsLink(link) &&
link[0] != '#' && !bytes.HasPrefix(link, byteMailto) {
lnk := string(link)
if r.IsWiki {
lnk = util.URLJoin("wiki", lnk)
}
link = []byte(util.URLJoin(r.URLPrefix, lnk))
}
description := string(link)
if l.Description != nil {
description = r.nodesAsString(l.Description...)
}
switch l.Kind() {
case "image":
r.WriteString(fmt.Sprintf(`<img src="%s" alt="%s" title="%s" />`, link, description, description))
case "video":
r.WriteString(fmt.Sprintf(`<video src="%s" title="%s">%s</video>`, link, description, description))
default:
r.WriteString(fmt.Sprintf(`<a href="%s" title="%s">%s</a>`, link, description, description))
}
}
func (r *Renderer) emptyClone() *Renderer {
wcopy := *(r.HTMLWriter)
wcopy.Builder = strings.Builder{}
rcopy := *r
rcopy.HTMLWriter = &wcopy
wcopy.ExtendingWriter = &rcopy
return &rcopy
}
func (r *Renderer) nodesAsString(nodes ...org.Node) string {
tmp := r.emptyClone()
org.WriteNodes(tmp, nodes...)
return tmp.String()
}

View File

@ -27,12 +27,12 @@ func TestRender_StandardLinks(t *testing.T) {
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
googleRendered := `<p><a href="https://google.com/" title="https://google.com/">https://google.com/</a></p>`
googleRendered := "<p>\n<a href=\"https://google.com/\" title=\"https://google.com/\">https://google.com/</a>\n</p>"
test("[[https://google.com/]]", googleRendered)
lnk := util.URLJoin(AppSubURL, "WikiPage")
test("[[WikiPage][WikiPage]]",
`<p><a href="`+lnk+`" title="WikiPage">WikiPage</a></p>`)
"<p>\n<a href=\""+lnk+"\" title=\"WikiPage\">WikiPage</a>\n</p>")
}
func TestRender_Images(t *testing.T) {
@ -45,10 +45,8 @@ func TestRender_Images(t *testing.T) {
}
url := "../../.images/src/02/train.jpg"
title := "Train"
result := util.URLJoin(AppSubURL, url)
test(
"[[file:"+url+"]["+title+"]]",
`<p><a href="`+result+`"><img src="`+result+`" alt="`+title+`" title="`+title+`" /></a></p>`)
test("[[file:"+url+"]]",
"<p>\n<img src=\""+result+"\" alt=\""+result+"\" title=\""+result+"\" />\n</p>")
}

View File

@ -74,6 +74,11 @@ func (r *indexerNotifier) NotifyUpdateComment(doer *models.User, c *models.Comme
func (r *indexerNotifier) NotifyDeleteComment(doer *models.User, comment *models.Comment) {
if comment.Type == models.CommentTypeComment {
if err := comment.LoadIssue(); err != nil {
log.Error("LoadIssue: %v", err)
return
}
var found bool
if comment.Issue.Comments != nil {
for i := 0; i < len(comment.Issue.Comments); i++ {

View File

@ -277,3 +277,124 @@ func (m *webhookNotifier) NotifyNewIssue(issue *models.Issue) {
go models.HookQueue.Add(issue.RepoID)
}
}
func (m *webhookNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) {
mode, _ := models.AccessLevel(issue.Poster, issue.Repo)
var err error
if issue.IsPull {
issue.PullRequest.Issue = issue
err = models.PrepareWebhooks(issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{
Action: api.HookIssueEdited,
Index: issue.Index,
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
PullRequest: issue.PullRequest.APIFormat(),
Repository: issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(),
})
} else {
err = models.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{
Action: api.HookIssueEdited,
Index: issue.Index,
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
Issue: issue.APIFormat(),
Repository: issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go models.HookQueue.Add(issue.RepoID)
}
}
func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comment, oldContent string) {
if err := c.LoadPoster(); err != nil {
log.Error("LoadPoster: %v", err)
return
}
if err := c.LoadIssue(); err != nil {
log.Error("LoadIssue: %v", err)
return
}
if err := c.Issue.LoadAttributes(); err != nil {
log.Error("LoadAttributes: %v", err)
return
}
mode, _ := models.AccessLevel(doer, c.Issue.Repo)
if err := models.PrepareWebhooks(c.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentEdited,
Issue: c.Issue.APIFormat(),
Comment: c.APIFormat(),
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
Repository: c.Issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(),
IsPull: c.Issue.IsPull,
}); err != nil {
log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
} else {
go models.HookQueue.Add(c.Issue.Repo.ID)
}
}
func (m *webhookNotifier) NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
issue *models.Issue, comment *models.Comment) {
mode, _ := models.AccessLevel(doer, repo)
if err := models.PrepareWebhooks(repo, models.HookEventIssueComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentCreated,
Issue: issue.APIFormat(),
Comment: comment.APIFormat(),
Repository: repo.APIFormat(mode),
Sender: doer.APIFormat(),
IsPull: issue.IsPull,
}); err != nil {
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
} else {
go models.HookQueue.Add(repo.ID)
}
}
func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models.Comment) {
if err := comment.LoadPoster(); err != nil {
log.Error("LoadPoster: %v", err)
return
}
if err := comment.LoadIssue(); err != nil {
log.Error("LoadIssue: %v", err)
return
}
if err := comment.Issue.LoadAttributes(); err != nil {
log.Error("LoadAttributes: %v", err)
return
}
mode, _ := models.AccessLevel(doer, comment.Issue.Repo)
if err := models.PrepareWebhooks(comment.Issue.Repo, models.HookEventIssueComment, &api.IssueCommentPayload{
Action: api.HookIssueCommentDeleted,
Issue: comment.Issue.APIFormat(),
Comment: comment.APIFormat(),
Repository: comment.Issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(),
IsPull: comment.Issue.IsPull,
}); err != nil {
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
} else {
go models.HookQueue.Add(comment.Issue.Repo.ID)
}
}

View File

@ -11,6 +11,7 @@ import (
"strings"
"sync"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup/mdstripper"
"code.gitea.io/gitea/modules/setting"
)
@ -35,12 +36,8 @@ var (
// e.g. gogits/gogs#12345
crossReferenceIssueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-zA-Z-_\.]+/[0-9a-zA-Z-_\.]+#[0-9]+)(?:\s|$|\)|\]|\.(\s|$))`)
// Same as GitHub. See
// https://help.github.com/articles/closing-issues-via-commit-messages
issueCloseKeywords = []string{"close", "closes", "closed", "fix", "fixes", "fixed", "resolve", "resolves", "resolved"}
issueReopenKeywords = []string{"reopen", "reopens", "reopened"}
issueCloseKeywordsPat, issueReopenKeywordsPat *regexp.Regexp
issueKeywordsOnce sync.Once
giteaHostInit sync.Once
giteaHost string
@ -107,13 +104,40 @@ type RefSpan struct {
End int
}
func makeKeywordsPat(keywords []string) *regexp.Regexp {
return regexp.MustCompile(`(?i)(?:\s|^|\(|\[)(` + strings.Join(keywords, `|`) + `):? $`)
func makeKeywordsPat(words []string) *regexp.Regexp {
acceptedWords := parseKeywords(words)
if len(acceptedWords) == 0 {
// Never match
return nil
}
return regexp.MustCompile(`(?i)(?:\s|^|\(|\[)(` + strings.Join(acceptedWords, `|`) + `):? $`)
}
func init() {
issueCloseKeywordsPat = makeKeywordsPat(issueCloseKeywords)
issueReopenKeywordsPat = makeKeywordsPat(issueReopenKeywords)
func parseKeywords(words []string) []string {
acceptedWords := make([]string, 0, 5)
wordPat := regexp.MustCompile(`^[\pL]+$`)
for _, word := range words {
word = strings.ToLower(strings.TrimSpace(word))
// Accept Unicode letter class runes (a-z, á, à, ä, )
if wordPat.MatchString(word) {
acceptedWords = append(acceptedWords, word)
} else {
log.Info("Invalid keyword: %s", word)
}
}
return acceptedWords
}
func newKeywords() {
issueKeywordsOnce.Do(func() {
// Delay initialization until after the settings module is initialized
doNewKeywords(setting.Repository.PullRequest.CloseKeywords, setting.Repository.PullRequest.ReopenKeywords)
})
}
func doNewKeywords(close []string, reopen []string) {
issueCloseKeywordsPat = makeKeywordsPat(close)
issueReopenKeywordsPat = makeKeywordsPat(reopen)
}
// getGiteaHostName returns a normalized string with the local host name, with no scheme or port information
@ -310,13 +334,19 @@ func getCrossReference(content []byte, start, end int, fromLink bool) *rawRefere
}
func findActionKeywords(content []byte, start int) (XRefAction, *RefSpan) {
m := issueCloseKeywordsPat.FindSubmatchIndex(content[:start])
if m != nil {
return XRefActionCloses, &RefSpan{Start: m[2], End: m[3]}
newKeywords()
var m []int
if issueCloseKeywordsPat != nil {
m = issueCloseKeywordsPat.FindSubmatchIndex(content[:start])
if m != nil {
return XRefActionCloses, &RefSpan{Start: m[2], End: m[3]}
}
}
m = issueReopenKeywordsPat.FindSubmatchIndex(content[:start])
if m != nil {
return XRefActionReopens, &RefSpan{Start: m[2], End: m[3]}
if issueReopenKeywordsPat != nil {
m = issueReopenKeywordsPat.FindSubmatchIndex(content[:start])
if m != nil {
return XRefActionReopens, &RefSpan{Start: m[2], End: m[3]}
}
}
return XRefActionNone, nil
}

View File

@ -12,161 +12,136 @@ import (
"github.com/stretchr/testify/assert"
)
type testFixture struct {
input string
expected []testResult
}
type testResult struct {
Index int64
Owner string
Name string
Issue string
Action XRefAction
RefLocation *RefSpan
ActionLocation *RefSpan
}
func TestFindAllIssueReferences(t *testing.T) {
type result struct {
Index int64
Owner string
Name string
Issue string
Action XRefAction
RefLocation *RefSpan
ActionLocation *RefSpan
}
type testFixture struct {
input string
expected []result
}
fixtures := []testFixture{
{
"Simply closes: #29 yes",
[]result{
[]testResult{
{29, "", "", "29", XRefActionCloses, &RefSpan{Start: 15, End: 18}, &RefSpan{Start: 7, End: 13}},
},
},
{
"#123 no, this is a title.",
[]result{},
[]testResult{},
},
{
" #124 yes, this is a reference.",
[]result{
[]testResult{
{124, "", "", "124", XRefActionNone, &RefSpan{Start: 0, End: 4}, nil},
},
},
{
"```\nThis is a code block.\n#723 no, it's a code block.```",
[]result{},
[]testResult{},
},
{
"This `#724` no, it's inline code.",
[]result{},
[]testResult{},
},
{
"This user3/repo4#200 yes.",
[]result{
[]testResult{
{200, "user3", "repo4", "200", XRefActionNone, &RefSpan{Start: 5, End: 20}, nil},
},
},
{
"This [one](#919) no, this is a URL fragment.",
[]result{},
[]testResult{},
},
{
"This [two](/user2/repo1/issues/921) yes.",
[]result{
[]testResult{
{921, "user2", "repo1", "921", XRefActionNone, nil, nil},
},
},
{
"This [three](/user2/repo1/pulls/922) yes.",
[]result{
[]testResult{
{922, "user2", "repo1", "922", XRefActionNone, nil, nil},
},
},
{
"This [four](http://gitea.com:3000/user3/repo4/issues/203) yes.",
[]result{
[]testResult{
{203, "user3", "repo4", "203", XRefActionNone, nil, nil},
},
},
{
"This [five](http://github.com/user3/repo4/issues/204) no.",
[]result{},
[]testResult{},
},
{
"This http://gitea.com:3000/user4/repo5/201 no, bad URL.",
[]result{},
[]testResult{},
},
{
"This http://gitea.com:3000/user4/repo5/pulls/202 yes.",
[]result{
[]testResult{
{202, "user4", "repo5", "202", XRefActionNone, nil, nil},
},
},
{
"This http://GiTeA.COM:3000/user4/repo6/pulls/205 yes.",
[]result{
[]testResult{
{205, "user4", "repo6", "205", XRefActionNone, nil, nil},
},
},
{
"Reopens #15 yes",
[]result{
[]testResult{
{15, "", "", "15", XRefActionReopens, &RefSpan{Start: 8, End: 11}, &RefSpan{Start: 0, End: 7}},
},
},
{
"This closes #20 for you yes",
[]result{
[]testResult{
{20, "", "", "20", XRefActionCloses, &RefSpan{Start: 12, End: 15}, &RefSpan{Start: 5, End: 11}},
},
},
{
"Do you fix user6/repo6#300 ? yes",
[]result{
[]testResult{
{300, "user6", "repo6", "300", XRefActionCloses, &RefSpan{Start: 11, End: 26}, &RefSpan{Start: 7, End: 10}},
},
},
{
"For 999 #1235 no keyword, but yes",
[]result{
[]testResult{
{1235, "", "", "1235", XRefActionNone, &RefSpan{Start: 8, End: 13}, nil},
},
},
{
"Which abc. #9434 same as above",
[]result{
[]testResult{
{9434, "", "", "9434", XRefActionNone, &RefSpan{Start: 11, End: 16}, nil},
},
},
{
"This closes #600 and reopens #599",
[]result{
[]testResult{
{600, "", "", "600", XRefActionCloses, &RefSpan{Start: 12, End: 16}, &RefSpan{Start: 5, End: 11}},
{599, "", "", "599", XRefActionReopens, &RefSpan{Start: 29, End: 33}, &RefSpan{Start: 21, End: 28}},
},
},
}
// Save original value for other tests that may rely on it
prevURL := setting.AppURL
setting.AppURL = "https://gitea.com:3000/"
for _, fixture := range fixtures {
expraw := make([]*rawReference, len(fixture.expected))
for i, e := range fixture.expected {
expraw[i] = &rawReference{
index: e.Index,
owner: e.Owner,
name: e.Name,
action: e.Action,
issue: e.Issue,
refLocation: e.RefLocation,
actionLocation: e.ActionLocation,
}
}
expref := rawToIssueReferenceList(expraw)
refs := FindAllIssueReferencesMarkdown(fixture.input)
assert.EqualValues(t, expref, refs, "Failed to parse: {%s}", fixture.input)
rawrefs := findAllIssueReferencesMarkdown(fixture.input)
assert.EqualValues(t, expraw, rawrefs, "Failed to parse: {%s}", fixture.input)
}
// Restore for other tests that may rely on the original value
setting.AppURL = prevURL
testFixtures(t, fixtures, "default")
type alnumFixture struct {
input string
@ -203,6 +178,35 @@ func TestFindAllIssueReferences(t *testing.T) {
}
}
func testFixtures(t *testing.T, fixtures []testFixture, context string) {
// Save original value for other tests that may rely on it
prevURL := setting.AppURL
setting.AppURL = "https://gitea.com:3000/"
for _, fixture := range fixtures {
expraw := make([]*rawReference, len(fixture.expected))
for i, e := range fixture.expected {
expraw[i] = &rawReference{
index: e.Index,
owner: e.Owner,
name: e.Name,
action: e.Action,
issue: e.Issue,
refLocation: e.RefLocation,
actionLocation: e.ActionLocation,
}
}
expref := rawToIssueReferenceList(expraw)
refs := FindAllIssueReferencesMarkdown(fixture.input)
assert.EqualValues(t, expref, refs, "[%s] Failed to parse: {%s}", context, fixture.input)
rawrefs := findAllIssueReferencesMarkdown(fixture.input)
assert.EqualValues(t, expraw, rawrefs, "[%s] Failed to parse: {%s}", context, fixture.input)
}
// Restore for other tests that may rely on the original value
setting.AppURL = prevURL
}
func TestRegExp_mentionPattern(t *testing.T) {
trueTestCases := []string{
"@Unknwon",
@ -294,3 +298,75 @@ func TestRegExp_issueAlphanumericPattern(t *testing.T) {
assert.False(t, issueAlphanumericPattern.MatchString(testCase))
}
}
func TestCustomizeCloseKeywords(t *testing.T) {
fixtures := []testFixture{
{
"Simplemente cierra: #29 yes",
[]testResult{
{29, "", "", "29", XRefActionCloses, &RefSpan{Start: 20, End: 23}, &RefSpan{Start: 12, End: 18}},
},
},
{
"Closes: #123 no, this English.",
[]testResult{
{123, "", "", "123", XRefActionNone, &RefSpan{Start: 8, End: 12}, nil},
},
},
{
"Cerró user6/repo6#300 yes",
[]testResult{
{300, "user6", "repo6", "300", XRefActionCloses, &RefSpan{Start: 7, End: 22}, &RefSpan{Start: 0, End: 6}},
},
},
{
"Reabre user3/repo4#200 yes",
[]testResult{
{200, "user3", "repo4", "200", XRefActionReopens, &RefSpan{Start: 7, End: 22}, &RefSpan{Start: 0, End: 6}},
},
},
}
issueKeywordsOnce.Do(func() {})
doNewKeywords([]string{"cierra", "cerró"}, []string{"reabre"})
testFixtures(t, fixtures, "spanish")
// Restore default settings
doNewKeywords(setting.Repository.PullRequest.CloseKeywords, setting.Repository.PullRequest.ReopenKeywords)
}
func TestParseCloseKeywords(t *testing.T) {
// Test parsing of CloseKeywords and ReopenKeywords
assert.Len(t, parseKeywords([]string{""}), 0)
assert.Len(t, parseKeywords([]string{" aa ", " bb ", "99", "#", "", "this is", "cc"}), 3)
for _, test := range []struct {
pattern string
match string
expected string
}{
{"close", "This PR will close ", "close"},
{"cerró", "cerró ", "cerró"},
{"cerró", "AQUÍ SE CERRÓ: ", "CERRÓ"},
{"закрывается", "закрывается ", "закрывается"},
{"κλείνει", "κλείνει: ", "κλείνει"},
{"关闭", "关闭 ", "关闭"},
{"閉じます", "閉じます ", "閉じます"},
{",$!", "", ""},
{"1234", "", ""},
} {
// The patern only needs to match the part that precedes the reference.
// getCrossReference() takes care of finding the reference itself.
pat := makeKeywordsPat([]string{test.pattern})
if test.expected == "" {
assert.Nil(t, pat)
} else {
assert.NotNil(t, pat)
res := pat.FindAllStringSubmatch(test.match, -1)
assert.Len(t, res, 1)
assert.Len(t, res[0], 2)
assert.EqualValues(t, test.expected, res[0][1])
}
}
}

View File

@ -59,6 +59,8 @@ var (
// Pull request settings
PullRequest struct {
WorkInProgressPrefixes []string
CloseKeywords []string
ReopenKeywords []string
} `ini:"repository.pull-request"`
// Issue Setting
@ -122,8 +124,14 @@ var (
// Pull request settings
PullRequest: struct {
WorkInProgressPrefixes []string
CloseKeywords []string
ReopenKeywords []string
}{
WorkInProgressPrefixes: []string{"WIP:", "[WIP]"},
// Same as GitHub. See
// https://help.github.com/articles/closing-issues-via-commit-messages
CloseKeywords: strings.Split("close,closes,closed,fix,fixes,fixed,resolve,resolves,resolved", ","),
ReopenKeywords: strings.Split("reopen,reopens,reopened", ","),
},
// Issue settings

View File

@ -39,6 +39,7 @@ var Service struct {
EnableTimetracking bool
DefaultEnableTimetracking bool
DefaultEnableDependencies bool
AllowCrossRepositoryDependencies bool
DefaultAllowOnlyContributorsToTrackTime bool
NoReplyAddress string
EnableUserHeatmap bool
@ -79,6 +80,7 @@ func newService() {
Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true)
}
Service.DefaultEnableDependencies = sec.Key("DEFAULT_ENABLE_DEPENDENCIES").MustBool(true)
Service.AllowCrossRepositoryDependencies = sec.Key("ALLOW_CROSS_REPOSITORY_DEPENDENCIES").MustBool(true)
Service.DefaultAllowOnlyContributorsToTrackTime = sec.Key("DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME").MustBool(true)
Service.NoReplyAddress = sec.Key("NO_REPLY_ADDRESS").MustString("noreply.example.org")
Service.EnableUserHeatmap = sec.Key("ENABLE_USER_HEATMAP").MustBool(true)

View File

@ -26,6 +26,13 @@ type PullRequestMeta struct {
Merged *time.Time `json:"merged_at"`
}
// RepositoryMeta basic repository information
type RepositoryMeta struct {
ID int64 `json:"id"`
Name string `json:"name"`
FullName string `json:"full_name"`
}
// Issue represents an issue in a repository
// swagger:model
type Issue struct {
@ -57,6 +64,7 @@ type Issue struct {
Deadline *time.Time `json:"due_date"`
PullRequest *PullRequestMeta `json:"pull_request"`
Repo *RepositoryMeta `json:"repository"`
}
// ListIssueOption list issue options

View File

@ -1,7 +1,5 @@
Attribution Assurance License
Copyright (c) 2002 by AUTHOR PROFESSIONAL IDENTIFICATION * URL "PROMOTIONAL
SLOGAN FOR AUTHOR'S PROFESSIONAL PRACTICE"
Attribution Assurance License Copyright (c) 2002 by AUTHOR PROFESSIONAL IDENTIFICATION
* URL "PROMOTIONAL SLOGAN FOR AUTHOR'S PROFESSIONAL PRACTICE"
All Rights Reserved ATTRIBUTION ASSURANCE LICENSE (adapted from the original
BSD license)

View File

@ -1,6 +1,6 @@
This software code is made available "AS IS" without warranties of any kind.
You may copy, display, modify and redistribute the software code either by
itself or as incorporated into your code; provided that > you do not remove
itself or as incorporated into your code; provided that you do not remove
any proprietary notices. Your use of this software code is at your own risk
and you waive any claim against Amazon Digital Services, Inc. or its affiliates
with respect to your use of this software code. (c) 2006 Amazon Digital Services,

View File

@ -4,7 +4,7 @@ Version 1.1 The Academic Free License applies to any original work of authorship
(the "Original Work") whose owner (the "Licensor") has placed the following
notice immediately following the copyright notice for the Original Work:
" Licensed under the Academic Free License version 1.1. "
"Licensed under the Academic Free License version 1.1."
Grant of License. Licensor hereby grants to any person obtaining a copy of
the Original Work ("You") a world-wide, royalty-free, non-exclusive, perpetual,

View File

@ -2,7 +2,7 @@ GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http s ://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
@ -597,7 +597,7 @@ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
You should have received a copy of the GNU Affero General Public License along
with this program. If not, see <http s ://www.gnu.org/licenses/>.
with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
@ -610,5 +610,4 @@ programs; see section 13 for the specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see <http
s ://www.gnu.org/licenses/>.
more information on this, and how to apply and follow the GNU AGPL, see <https://www.gnu.org/licenses/>.

View File

@ -2,7 +2,7 @@ GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http s ://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
@ -597,7 +597,7 @@ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
You should have received a copy of the GNU Affero General Public License along
with this program. If not, see <http s ://www.gnu.org/licenses/>.
with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
@ -610,5 +610,4 @@ programs; see section 13 for the specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU AGPL, see <http
s ://www.gnu.org/licenses/>.
more information on this, and how to apply and follow the GNU AGPL, see <https://www.gnu.org/licenses/>.

View File

@ -1,6 +1,5 @@
Adobe Systems Incorporated(r) Source Code License Agreement
Copyright(c) 2006 Adobe Systems Incorporated. All rights reserved.
Adobe Systems Incorporated(r) Source Code License Agreement Copyright(c) 2006
Adobe Systems Incorporated. All rights reserved.
Please read this Source Code License Agreement carefully before using the
source code.

View File

@ -1,8 +1,7 @@
Aladdin Free Public License
(Version 8, November 18, 1999)
Copyright (C) 1994, 1995, 1997, 1998, 1999 Aladdin Enterprises,
(Version 8, November 18, 1999) Copyright (C) 1994, 1995, 1997, 1998, 1999
Aladdin Enterprises,
Menlo Park, California, U.S.A. All rights reserved. NOTE: This License is
not the same as any of the GNU Licenses published by the Free Software Foundation.

View File

@ -1,6 +1,5 @@
Apache License 1.1
Copyright (c) 2000 The Apache Software Foundation . All rights reserved.
Apache License 1.1 Copyright (c) 2000 The Apache Software Foundation. All
rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

View File

@ -1,8 +1,6 @@
AUTOCONF CONFIGURE SCRIPT EXCEPTION
Version 3.0, 18 August 2009
Copyright © 2009 Free Software Foundation, Inc. <http://fsf.org/>
Version 3.0, 18 August 2009 Copyright © 2009 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

View File

@ -1,4 +1,4 @@
Copyright (c) <year> <owner> . All rights reserved.
Copyright (c) <year> <owner>. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

View File

@ -1,6 +1,5 @@
The FreeBSD Copyright
Copyright 1992-2012 The FreeBSD Project. All rights reserved.
The FreeBSD Copyright Copyright 1992-2012 The FreeBSD Project. All rights
reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

View File

@ -1,4 +1,4 @@
Copyright (c) <year> <owner> . All rights reserved.
Copyright (c) <year> <owner>. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

View File

@ -1,6 +1,4 @@
The Clear BSD License
Copyright (c) [xxxx]-[xxxx] [Owner Organization]
The Clear BSD License Copyright (c) [xxxx]-[xxxx] [Owner Organization]
All rights reserved.

View File

@ -1,4 +1,4 @@
Copyright (c) <year> <owner> . All rights reserved.
Copyright (c) <year> <owner>. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

View File

@ -202,4 +202,4 @@ consent of Creative Commons. Any permitted use will be in compliance with
Creative Commons' then-current trademark usage guidelines, as may be published
on its website or otherwise made available upon request from time to time.
Creative Commons may be contacted at http s ://creativecommons.org/.
Creative Commons may be contacted at https://creativecommons.org/.

View File

@ -378,7 +378,7 @@ portions of the Covered Code under Your choice of the NPL or the alternative
licenses, if any, specified by the Initial Developer in the file described
in Exhibit A. EXHIBIT A - CUA Office Public License.
" The contents of this file are subject to the CUA Office Public License Version
"The contents of this file are subject to the CUA Office Public License Version
1.0 (the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://cuaoffice.sourceforge.net/
@ -402,7 +402,7 @@ to allow others to use your version of this file under the CUAPL, indicate
your decision by deleting the provisions above and replace them with the notice
and other provisions required by the [___] License. If you do not delete the
provisions above, a recipient may use your version of this file under either
the CUAPL or the [___] License. "
the CUAPL or the [___] License."
[NOTE: The text of this Exhibit A may differ slightly from the text of the
notices in the Source Code files of the Original Code. You should use the

View File

@ -1,11 +1,10 @@
Condor Public License
Version 1.1, October 30, 2003
Copyright © 1990-2006 Condor Team, Computer Sciences Department, University
of Wisconsin-Madison, Madison, WI. All Rights Reserved. For more information
contact: Condor Team, Attention: Professor Miron Livny, Dept of Computer Sciences,
1210 W. Dayton St., Madison, WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
Version 1.1, October 30, 2003 Copyright © 1990-2006 Condor Team, Computer
Sciences Department, University of Wisconsin-Madison, Madison, WI. All Rights
Reserved. For more information contact: Condor Team, Attention: Professor
Miron Livny, Dept of Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
(608) 262-0856 or miron@cs.wisc.edu.
This software referred to as the Condor® Version 6.x software ("Software")
was developed by the Condor Project, Condor Team, Computer Sciences Department,

View File

@ -1,6 +1,5 @@
Cube game engine source code, 20 dec 2003 release.
Copyright (C) 2001-2003 Wouter van Oortmerssen.
Cube game engine source code, 20 dec 2003 release. Copyright (C) 2001-2003
Wouter van Oortmerssen.
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the

View File

@ -1,6 +1,4 @@
COPYRIGHT NOTIFICATION
(C) COPYRIGHT 2004 UNIVERSITY OF CHICAGO
COPYRIGHT NOTIFICATION (C) COPYRIGHT 2004 UNIVERSITY OF CHICAGO
This program discloses material protectable under copyright laws of the United
States. Permission to copy and modify this software and its documentation

View File

@ -1,6 +1,4 @@
EU DataGrid Software License
Copyright (c) 2001 EU DataGrid. All rights reserved.
EU DataGrid Software License Copyright (c) 2001 EU DataGrid. All rights reserved.
This software includes voluntary contributions made to the EU DataGrid. For
more information on the EU DataGrid, please see http://www.eu-datagrid.org/.

View File

@ -1,10 +1,9 @@
European Union Public Licence V.1.0
EUPL (c) the European Community 2007 This European Union Public Licence (the
"EUPL") applies to the Work or Software (as defined below) which is provided
under the terms of this Licence. Any use of the Work, other than as authorised
under this Licence is prohibited (to the extent such use is covered by a right
of the copyright holder of the Work).
European Union Public Licence V.1.0 EUPL (c) the European Community 2007 This
European Union Public Licence (the "EUPL") applies to the Work or Software
(as defined below) which is provided under the terms of this Licence. Any
use of the Work, other than as authorised under this Licence is prohibited
(to the extent such use is covered by a right of the copyright holder of the
Work).
The Original Work is provided under the terms of this Licence when the Licensor
(as defined below) has placed the following notice immediately following the

View File

@ -1,6 +1,4 @@
European Union Public Licence V. 1.1
EUPL (c) the European Community 2007
European Union Public Licence V. 1.1 EUPL (c) the European Community 2007
This European Union Public Licence (the "EUPL") applies to the Work or Software
(as defined below) which is provided under the terms of this Licence. Any

View File

@ -1,6 +1,5 @@
Entessa Public License Version. 1.0
Copyright (c) 2003 Entessa, LLC. All rights reserved.
Entessa Public License Version. 1.0 Copyright (c) 2003 Entessa, LLC. All rights
reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

View File

@ -1,6 +1,4 @@
Fair License
<Copyright Information>
Fair License <Copyright Information>
Usage of the works is permitted provided that this instrument is retained
with the works, so that any entity that uses the works is notified of this

View File

@ -1,9 +1,7 @@
GNU Free Documentation License
Version 1.3, 3 November 2008
Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
<http://fsf.org/>
Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free
Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.

View File

@ -1,9 +1,7 @@
GNU Free Documentation License
Version 1.3, 3 November 2008
Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
<http://fsf.org/>
Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free
Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.

View File

@ -1,6 +1,4 @@
GL2PS LICENSE Version 2, November 2003
Copyright (C) 2003, Christophe Geuzaine
GL2PS LICENSE Version 2, November 2003 Copyright (C) 2003, Christophe Geuzaine
Permission to use, copy, and distribute this software and its documentation
for any purpose with or without fee is hereby granted, provided that the copyright

View File

@ -4,7 +4,7 @@ Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 , USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
@ -272,9 +272,9 @@ them to the start of each source file to most effectively convey the exclusion
of warranty; and each file should have at least the "copyright" line and a
pointer to where the full notice is found.
< one line to give the program's name and an idea of what it does. >
<one line to give the program's name and an idea of what it does.>
Copyright (C) < yyyy > < name of author >
Copyright (C)< yyyy> <name of author>
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -287,7 +287,7 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
Street, Fifth Floor, Boston, MA 02110-1301 , USA.
Street, Fifth Floor, Boston, MA 02110-1301, USA.
Also add information on how to contact you by electronic and paper mail.
@ -311,7 +311,7 @@ is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision'
(which makes passes at compilers) written by James Hacker.
< signature of Ty Coon > , 1 April 1989 Ty Coon, President of Vice This General
<signature of Ty Coon >, 1 April 1989 Ty Coon, President of Vice This General
Public License does not permit incorporating your program into proprietary
programs. If your program is a subroutine library, you may consider it more
useful to permit linking proprietary applications with the library. If this

View File

@ -4,7 +4,7 @@ Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 , USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
@ -287,7 +287,7 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
Street, Fifth Floor, Boston, MA 02110-1301 , USA.
Street, Fifth Floor, Boston, MA 02110-1301, USA.
Also add information on how to contact you by electronic and paper mail.
@ -311,7 +311,7 @@ is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision'
(which makes passes at compilers) written by James Hacker.
< signature of Ty Coon > , 1 April 1989 Ty Coon, President of Vice This General
<signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General
Public License does not permit incorporating your program into proprietary
programs. If your program is a subroutine library, you may consider it more
useful to permit linking proprietary applications with the library. If this

View File

@ -2,7 +2,7 @@ GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. <http s ://fsf.org/>
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
@ -595,7 +595,7 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http s ://www.gnu.org/licenses/>.
this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
@ -615,12 +615,11 @@ be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU GPL, see <http
s ://www.gnu.org/licenses/>.
more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General Public
License instead of this License. But first, please read <http s ://www.gnu.org/
License instead of this License. But first, please read <https://www.gnu.org/
licenses /why-not-lgpl.html>.

View File

@ -2,7 +2,7 @@ GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. <http s ://fsf.org/>
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
@ -595,7 +595,7 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http s ://www.gnu.org/licenses/>.
this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
@ -615,12 +615,11 @@ be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. For
more information on this, and how to apply and follow the GNU GPL, see <http
s ://www.gnu.org/licenses/>.
more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General Public
License instead of this License. But first, please read <http s ://www.gnu.org/
License instead of this License. But first, please read <https://www.gnu.org/
licenses /why-not-lgpl.html>.

View File

@ -1,10 +1,8 @@
Historical Permission Notice and Disclaimer
<copyright notice>
Historical Permission Notice and Disclaimer <copyright notice>
Permission to use, copy, modify and distribute this software and its documentation
for any purpose and without fee is hereby granted, provided that the above
copyright notice appear in all copies , and that both that the copyright notice
copyright notice appear in all copies, and that both that the copyright notice
and this permission notice appear in supporting documentation , and that the
name of <copyright holder> <or related entities> not be used in advertising
or publicity pertaining to distribution of the software without specific,

View File

@ -1,8 +1,7 @@
ICU License - ICU 1.8.1 and later
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1995-2014 International Business Machines Corporation and others
COPYRIGHT AND PERMISSION NOTICE Copyright (c) 1995-2014 International Business
Machines Corporation and others
All rights reserved.

View File

@ -1,6 +1,4 @@
ISC License
Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
ISC License Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
Copyright (c) 1995-2003 by Internet Software Consortium

View File

@ -64,10 +64,9 @@ you need to acknowledge the use of the ImageMagick software;
Terms and Conditions for Use, Reproduction, and Distribution
The legally binding and authoritative terms and conditions for use, reproduction,
and distribution of ImageMagick follow:
Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization dedicated
to making software imaging solutions freely available.
and distribution of ImageMagick follow: Copyright 1999-2013 ImageMagick Studio
LLC, a non-profit organization dedicated to making software imaging solutions
freely available.
1. Definitions.

View File

@ -1,6 +1,4 @@
Info-ZIP License
Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
Info-ZIP License Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
For the purposes of this copyright and license, "Info-ZIP" is defined as the
following set of individuals:

View File

@ -1,6 +1,4 @@
Intel Open Source License
Copyright (c) 1996-2000 Intel Corporation
Intel Open Source License Copyright (c) 1996-2000 Intel Corporation
All rights reserved.

View File

@ -429,7 +429,7 @@ in Exhibit A.
EXHIBIT A - InterBase Public License.
" The contents of this file are subject to the Interbase Public License Version
"The contents of this file are subject to the Interbase Public License Version
1.0 (the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.Interbase.com/IPL.html

View File

@ -1,6 +1,4 @@
JSON License
Copyright (c) 2002 JSON.org
JSON License Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,4 @@
JasPer License Version 2.0
Copyright (c) 2001-2006 Michael David Adams
JasPer License Version 2.0 Copyright (c) 2001-2006 Michael David Adams
Copyright (c) 1999-2000 Image Power, Inc.

View File

@ -1,6 +1,6 @@
Licence Art Libre 1.3 (LAL 1.3)
Préambule :
Préambule :
Avec la Licence Art Libre, l'autorisation est donnée de copier, de diffuser
et de transformer librement les œuvres dans le respect des droits de l'auteur.
@ -12,44 +12,44 @@ d'expression.
Si, en règle générale, l'application du droit d'auteur conduit à restreindre
l'accès aux œuvres de l'esprit, la Licence Art Libre, au contraire, le favorise.
L'intention est d'autoriser l'utilisation des ressources d'une œuvre ; créer
L'intention est d'autoriser l'utilisation des ressources d'une œuvre ; créer
de nouvelles conditions de création pour amplifier les possibilités de création.
La Licence Art Libre permet d'avoir jouissance des œuvres tout en reconnaissant
les droits et les responsabilités de chacun.
Avec le développement du numérique, l'invention d'internet et des logiciels
libres, les modalités de création ont évolué : les productions de l'esprit
libres, les modalités de création ont évolué : les productions de l'esprit
s'offrent naturellement à la circulation, à l'échange et aux transformations.
Elles se prêtent favorablement à la réalisation d'œuvres communes que chacun
peut augmenter pour l'avantage de tous.
C'est la raison essentielle de la Licence Art Libre : promouvoir et protéger
ces productions de l'esprit selon les principes du copyleft : liberté d'usage,
C'est la raison essentielle de la Licence Art Libre : promouvoir et protéger
ces productions de l'esprit selon les principes du copyleft : liberté d'usage,
de copie, de diffusion, de transformation et interdiction d'appropriation
exclusive.
Définitions :
Définitions :
Nous désignons par « œuvre », autant l'œuvre initiale, les œuvres conséquentes,
que l'œuvre commune telles que définies ci-après :
Nous désignons par « œuvre », autant l'œuvre initiale, les œuvres conséquentes,
que l'œuvre commune telles que définies ci-après :
L'œuvre commune : Il s'agit d'une œuvre qui comprend l'œuvre initiale ainsi
L'œuvre commune : Il s'agit d'une œuvre qui comprend l'œuvre initiale ainsi
que toutes les contributions postérieures (les originaux conséquents et les
copies). Elle est créée à l'initiative de l'auteur initial qui par cette licence
définit les conditions selon lesquelles les contributions sont faites.
L'œuvre initiale : C'est-à-dire l'œuvre créée par l'initiateur de l'œuvre
L'œuvre initiale : C'est-à-dire l'œuvre créée par l'initiateur de l'œuvre
commune dont les copies vont être modifiées par qui le souhaite.
Les œuvres conséquentes : C'est-à-dire les contributions des auteurs qui participent
Les œuvres conséquentes : C'est-à-dire les contributions des auteurs qui participent
à la formation de l'œuvre commune en faisant usage des droits de reproduction,
de diffusion et de modification que leur confère la licence.
Originaux (sources ou ressources de l'œuvre) : Chaque exemplaire daté de l'œuvre
Originaux (sources ou ressources de l'œuvre) : Chaque exemplaire daté de l'œuvre
initiale ou conséquente que leurs auteurs présentent comme référence pour
toutes actualisations, interprétations, copies ou reproductions ultérieures.
Copie : Toute reproduction d'un original au sens de cette licence.
Copie : Toute reproduction d'un original au sens de cette licence.
1- OBJET.
@ -70,33 +70,30 @@ personne, quelle que soit la technique employée.
Vous pouvez diffuser librement les copies de ces œuvres, modifiées ou non,
quel que soit le support, quel que soit le lieu, à titre onéreux ou gratuit,
si vous respectez toutes les conditions suivantes :
si vous respectez toutes les conditions suivantes :
1. joindre aux copies cette licence à l'identique ou indiquer précisément
où se trouve la licence ;
où se trouve la licence ;
2. indiquer au destinataire le nom de chaque auteur des originaux, y compris
le vôtre si vous avez modifié l'œuvre ;
le vôtre si vous avez modifié l'œuvre ;
3. indiquer au destinataire où il pourrait avoir accès aux originaux (initiaux
et/ou conséquents).
Les auteurs des originaux pourront, s'ils le souhaitent, vous autoriser à
diffuser l'original dans les mêmes conditions que les copies.
et/ou conséquents). Les auteurs des originaux pourront, s'ils le souhaitent,
vous autoriser à diffuser l'original dans les mêmes conditions que les copies.
2.3 LA LIBERTÉ DE MODIFIER.
Vous avez la liberté de modifier les copies des originaux (initiaux et conséquents)
dans le respect des conditions suivantes :
dans le respect des conditions suivantes :
1. celles prévues à l'article 2.2 en cas de diffusion de la copie modifiée
;
1. celles prévues à l'article 2.2 en cas de diffusion de la copie modifiée ;
2. indiquer qu'il s'agit d'une œuvre modifiée et, si possible, la nature de
la modification ;
la modification ;
3. diffuser cette œuvre conséquente avec la même licence ou avec toute licence
compatible ;
compatible ;
4. Les auteurs des originaux pourront, s'ils le souhaitent, vous autoriser
à modifier l'original dans les mêmes conditions que les copies.
@ -104,11 +101,12 @@ compatible ;
3. DROITS CONNEXES.
Les actes donnant lieu à des droits d'auteur ou des droits voisins ne doivent
pas constituer un obstacle aux libertés conférées par cette licence. C'est
pourquoi, par exemple, les interprétations doivent être soumises à la même
licence ou une licence compatible. De même, l'intégration de l'œuvre à une
base de données, une compilation ou une anthologie ne doit pas faire obstacle
à la jouissance de l'œuvre telle que définie par cette licence.
pas constituer un obstacle aux libertés conférées par cette licence.
C'est pourquoi, par exemple, les interprétations doivent être soumises à la
même licence ou une licence compatible. De même, l'intégration de l'œuvre
à une base de données, une compilation ou une anthologie ne doit pas faire
obstacle à la jouissance de l'œuvre telle que définie par cette licence.
4. L' INTÉGRATION DE L'ŒUVRE.
@ -121,16 +119,16 @@ compatible.
5. CRITÈRES DE COMPATIBILITÉ.
Une licence est compatible avec la LAL si et seulement si :
Une licence est compatible avec la LAL si et seulement si :
1. elle accorde l'autorisation de copier, diffuser et modifier des copies
de l'œuvre, y compris à des fins lucratives, et sans autres restrictions que
celles qu'impose le respect des autres critères de compatibilité ;
celles qu'impose le respect des autres critères de compatibilité ;
2. elle garantit la paternité de l'œuvre et l'accès aux versions antérieures
de l'œuvre quand cet accès est possible ;
de l'œuvre quand cet accès est possible ;
3. elle reconnaît la LAL également compatible (réciprocité) ;
3. elle reconnaît la LAL également compatible (réciprocité) ;
4. elle impose que les modifications faites sur l'œuvre soient soumises à
la même licence ou encore à une licence répondant aux critères de compatibilité

View File

@ -1,8 +1,6 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA

View File

@ -1,8 +1,6 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA

View File

@ -2,7 +2,7 @@ GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http s ://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.

View File

@ -2,7 +2,7 @@ GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http s ://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.

View File

@ -1,8 +1,6 @@
LaTeX Project Public License
LPPL Version 1.0 1999-03-01
Copyright 1999 LaTeX3 Project
LPPL Version 1.0 1999-03-01 Copyright 1999 LaTeX3 Project
Everyone is permitted to copy and distribute verbatim copies of this license
document, but modification is not allowed.

View File

@ -2,9 +2,7 @@ The LaTeX Project Public License
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
LPPL Version 1.1 1999-07-10
Copyright 1999 LaTeX3 Project
LPPL Version 1.1 1999-07-10 Copyright 1999 LaTeX3 Project
Everyone is allowed to distribute verbatim copies of this license document,
but modification of it is not allowed.

View File

@ -2,9 +2,7 @@ The LaTeX Project Public License
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
LPPL Version 1.2 1999-09-03
Copyright 1999 LaTeX3 Project
LPPL Version 1.2 1999-09-03 Copyright 1999 LaTeX3 Project
Everyone is allowed to distribute verbatim copies of this license document,
but modification of it is not allowed.

View File

@ -2,9 +2,7 @@ The LaTeX Project Public License
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
LPPL Version 1.3a 2004-10-01
Copyright 1999 2002-04 LaTeX3 Project
LPPL Version 1.3a 2004-10-01 Copyright 1999 2002-04 LaTeX3 Project
Everyone is allowed to distribute verbatim copies of this license document,
but modification of it is not allowed.

View File

@ -2,9 +2,7 @@ The LaTeX Project Public License
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
LPPL Version 1.3c 2008-05-04
Copyright 1999 2002-2008 LaTeX3 Project
LPPL Version 1.3c 2008-05-04 Copyright 1999 2002-2008 LaTeX3 Project
Everyone is allowed to distribute verbatim copies of this license document,
but modification of it is not allowed.

View File

@ -1,6 +1,4 @@
MIT License
Copyright (c) <year> <copyright holders>
MIT License Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,22 +1,17 @@
Copyright 1989, 1991, 1992 by Carnegie Mellon University
<copyright notice> By obtaining, using, and/or copying this software and/or
its associated documentation, you agree that you have read, understood, and
will comply with the following terms and conditions:
Derivative Work - 1996, 1998-2000 Copyright 1996, 1998-2000 The Regents of
the University of California
Permission to use, copy, modify, and distribute this software and its associated
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appears in all copies, and that both that
copyright notice and this permission notice appear in supporting documentation,
and that the name of the copyright holder not be used in advertising or publicity
pertaining to distribution of the software without specific, written permission.
All Rights Reserved
Permission to use, copy, modify and distribute this software and its documentation
for any purpose and without fee is hereby granted, provided that the above
copyright notice appears in all copies and that both that copyright notice
and this permission notice appear in supporting documentation, and that the
name of CMU and The Regents of the University of California not be used in
advertising or publicity pertaining to distribution of the software without
specific written permission.
CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL CMU OR THE REGENTS OF THE UNIVERSITY OF CALIFORNIA
BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE COPYRIGHT HOLDER DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM THE LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@ -319,7 +319,7 @@ of Covered Code you made available, the revenues you received from utilizing
such rights, and other relevant factors. You agree to work with affected parties
to distribute responsibility on an equitable basis. EXHIBIT A.
" The contents of this file are subject to the Mozilla Public License Version
"The contents of this file are subject to the Mozilla Public License Version
1.0 (the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
@ -329,4 +329,4 @@ the specific language governing rights and limitations under the License.
The Original Code is _____ . The Initial Developer of the Original Code is
_____ . Portions created by _____ are Copyright (C) _____ . All Rights Reserved.
Contributor(s): _____ . "
Contributor(s): _____ ."

View File

@ -389,7 +389,7 @@ portions of the Covered Code under Your choice of the MPL or the alternative
licenses, if any, specified by the Initial Developer in the file described
in Exhibit A. Exhibit A - Mozilla Public License.
" The contents of this file are subject to the Mozilla Public License Version
"The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
@ -414,7 +414,7 @@ to allow others to use your version of this file under the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the [___] License. If you do not delete the
provisions above, a recipient may use your version of this file under either
the MPL or the [___] License. "
the MPL or the [___] License."
NOTE: The text of this Exhibit A may differ slightly from the text of the
notices in the Source Code files of the Original Code. You should use the

View File

@ -1,6 +1,4 @@
Software License for MTL
Copyright (c) 2007 The Trustees of Indiana University.
Software License for MTL Copyright (c) 2007 The Trustees of Indiana University.
2008 Dresden University of Technology and the Trustees of Indiana University.

View File

@ -1,8 +1,6 @@
MakeIndex Distribution Notice
11/11/1989
Copyright (C) 1989 by Chen & Harrison International Systems, Inc.
11/11/1989 Copyright (C) 1989 by Chen & Harrison International Systems, Inc.
Copyright (C) 1988 by Olivetti Research Center

View File

@ -1,8 +1,4 @@
MirOS License
Copyright [YEAR]
[NAME] [EMAIL]
The MirOS Licence Copyright [YEAR] [NAME] [EMAIL]
Provided that these terms and disclaimer and all copyright notices are retained
or reproduced in an accompanying document, permission is granted to deal in
@ -15,50 +11,4 @@ intent or gross negligence. In no event may a licensor, author or contributor
be held liable for indirect, direct, other damage, loss, or other issues arising
in any way out of dealing in the work, even if advised of the possibility
of such damage or existence of a defect, except proven that it results out
of said person's immediate fault when using the work as intended. I_N_S_T_R_U_C_T_I_O_N_S_:_
To apply the template(1) specify the years of copyright (separated by comma,
not as a range), the legal names of the copyright holders, and the real names
of the authors if different. Avoid adding text.
R_A_T_I_O_N_A_L_E_:_
This licence is apt for any kind of work (such as source code, fonts, documentation,
graphics, sound etc.) and the preferred terms for work added to MirBSD. It
has been drafted as universally usable equivalent of the "historic permission
notice"(2) adapted to Europen law because in some (droit d'auteur) countries
authors cannot disclaim all liabi lities. Compliance to DFSG(3) 1.1 is ensured,
and GPLv2 compatibility is asserted unless advertising clauses are used. The
MirOS Licence is certified to conform to OKD(4) 1.0 and OSD(5) 1.9, and qualifies
as a Free Software(6) and also Free Documentation(7) licence and is included
in some relevant lists(8)(9)(10).
We believe you are not liable for work inserted which is intellectual property
of third parties, if you were not aware of the fact, act appropriately as
soon as you become aware of that problem, seek an amicable solution for all
parties, and never knowingly distribute a work without being authorised to
do so by its licensors.
R_E_F_E_R_E_N_C_E_S_:_
(1) also at http://mirbsd.de/MirOS-Licence
(2) http://www.opensource.org/licenses/historical.php
(3) http://www.debian.org/social_contract#guidelines
(4) http://www.opendefinition.org/1.0
(5) http://www.opensource.org/docs/osd
(6) http://www.gnu.org/philosophy/free-sw.html
(7) http://www.gnu.org/philosophy/free-doc.html
(8) http://www.ifross.de/ifross_html/lizenzcenter.html
(9) http://www.opendefinition.org/licenses
(10) http://opensource.org/licenses/miros.html
of said person's immediate fault when using the work as intended.

View File

@ -23,10 +23,9 @@ copyright notice and historical background appear in all copies and that both
the copyright notice and historical background and this permission notice
appear in supporting documentation, and that the names of MIT, HIS, BULL or
BULL HN not be used in advertising or publicity pertaining to distribution
of the programs without specific prior written permission.
Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information
Systems Inc.
of the programs without specific prior written permission. Copyright 1972
by Massachusetts Institute of Technology and Honeywell Information Systems
Inc.
Copyright 2006 by BULL HN Information Systems Inc.

View File

@ -1,9 +1,8 @@
The Net Boolean Public License
Version 1, 22 August 1998 Copyright 1998, Net Boolean Incorporated, Redwood
City, California, USA All Rights Reserved. Note: This license is derived from
the "Artistic License" as distributed with the Perl Programming Language.
Its terms are different from those of the "Artistic License."
The Net Boolean Public License Version 1, 22 August 1998 Copyright 1998, Net
Boolean Incorporated, Redwood City, California, USA All Rights Reserved. Note:
This license is derived from the "Artistic License" as distributed with the
Perl Programming Language. Its terms are different from those of the "Artistic
License."
PREAMBLE

View File

@ -1,6 +1,5 @@
University of Illinois/NCSA Open Source License
Copyright (c) <Year> <Owner Organization Name> . All rights reserved.
University of Illinois/NCSA Open Source License Copyright (c) <Year> <Owner
Organization Name>. All rights reserved.
Developed by:

View File

@ -1,6 +1,4 @@
NETHACK GENERAL PUBLIC LICENSE
(Copyright 1989 M. Stephenson)
NETHACK GENERAL PUBLIC LICENSE (Copyright 1989 M. Stephenson)
(Based on the BISON general public license, copyright 1988 Richard M. Stallman)

View File

@ -1,6 +1,5 @@
NTP License (NTP)
Copyright (c) (CopyrightHoldersName) (From 4-digit-year)-(To 4-digit-year)
NTP License (NTP) Copyright (c) (CopyrightHoldersName) (From 4-digit-year)-(To
4-digit-year)
Permission to use, copy, modify, and distribute this software and its documentation
for any purpose with or without fee is hereby granted, provided that the above

View File

@ -1,6 +1,5 @@
NAUMEN Public License
This software is Copyright (c) NAUMEN (tm) and Contributors. All rights reserved.
NAUMEN Public License This software is Copyright (c) NAUMEN (tm) and Contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

View File

@ -1,6 +1,5 @@
---- Part 1: CMU/UCD copyright notice: (BSD like) -----
Copyright 1989, 1991, 1992 by Carnegie Mellon University
---- Part 1: CMU/UCD copyright notice: (BSD like) ----- Copyright 1989, 1991,
1992 by Carnegie Mellon University
Derivative Work - 1996, 1998-2000 Copyright 1996, 1998-2000 The Regents of
the University of California
@ -79,10 +78,9 @@ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---- Part 4: Sun Microsystems, Inc. copyright notice (BSD) -----
Copyright © 2003 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
California 95054, U.S.A. All rights reserved.
---- Part 4: Sun Microsystems, Inc. copyright notice (BSD) ----- Copyright
© 2003 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California
95054, U.S.A. All rights reserved.
Use is subject to license terms below.
@ -174,7 +172,6 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---- Part 7: Fabasoft R&D Software GmbH & Co KG copyright notice (BSD) -----
Copyright (c) Fabasoft R&D Software GmbH & Co KG, 2003 oss@fabasoft.com Author:
Bernhard Penz
@ -203,9 +200,8 @@ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---- Part 8: Apple Inc. copyright notice (BSD) -----
Copyright (c) 2007 Apple Inc. All rights reserved.
---- Part 8: Apple Inc. copyright notice (BSD) ----- Copyright (c) 2007 Apple
Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

View File

@ -2,9 +2,8 @@ OCLC Research Public License 2.0
Terms & Conditions Of Use
May, 2002
Copyright © 2002. OCLC Online Computer Library Center, Inc. All Rights Reserved
May, 2002 Copyright © 2002. OCLC Online Computer Library Center, Inc. All
Rights Reserved
PLEASE READ THIS DOCUMENT CAREFULLY. BY DOWNLOADING OR USING THE CODE BASE
AND/OR DOCUMENTATION ACCOMPANYING THIS LICENSE (THE "License"), YOU AGREE
@ -79,7 +78,7 @@ If you distribute the Program in a form to which the recipient can make Modifica
addition, each source and data file of the Program and any Modification you
distribute must contain the following notice:
" Copyright (c) 2000- (insert then current year) OCLC Online Computer Library
"Copyright (c) 2000- (insert then current year) OCLC Online Computer Library
Center, Inc. and other contributors . All rights reserved. The contents of
this file, as updated from time to time by the OCLC Office of Research, are
subject to OCLC Research Public License Version 2.0 (the "License"); you may
@ -93,7 +92,7 @@ OCLC Research. For more information on OCLC Research, please see http://www.oclc
The Original Code is ______________________________ . The Initial Developer
of the Original Code is ________________________ . Portions created by ______________________
are Copyright (C) ____________________________ . All Rights Reserved. Contributor(s):
______________________________________ . "
______________________________________ ."
C. Requirements for a Distribution of Non-modifiable Code

View File

@ -1,10 +1,9 @@
The OpenLDAP Public License
Version 1.1, 25 August 1998
Copyright 1998, The OpenLDAP Foundation. All Rights Reserved. Note: This license
is derived from the "Artistic License" as distributed with the Perl Programming
Language. Its terms are different from those of the "Artistic License."
Version 1.1, 25 August 1998 Copyright 1998, The OpenLDAP Foundation. All Rights
Reserved. Note: This license is derived from the "Artistic License" as distributed
with the Perl Programming Language. Its terms are different from those of
the "Artistic License."
PREAMBLE

View File

@ -1,10 +1,9 @@
The OpenLDAP Public License
Version 1.2, 1 September 1998
Copyright 1998, The OpenLDAP Foundation. All Rights Reserved. Note: This license
is derived from the "Artistic License" as distributed with the Perl Programming
Language. As differences may exist, the complete license should be read.
Version 1.2, 1 September 1998 Copyright 1998, The OpenLDAP Foundation. All
Rights Reserved. Note: This license is derived from the "Artistic License"
as distributed with the Perl Programming Language. As differences may exist,
the complete license should be read.
PREAMBLE

View File

@ -1,11 +1,9 @@
The OpenLDAP Public License
Version 1.3, 17 January 1999
Copyright 1998-1999, The OpenLDAP Foundation. All Rights Reserved. Note: This
license is derived from the "Artistic License" as distributed with the Perl
Programming Language. As significant differences exist, the complete license
should be read.
Version 1.3, 17 January 1999 Copyright 1998-1999, The OpenLDAP Foundation.
All Rights Reserved. Note: This license is derived from the "Artistic License"
as distributed with the Perl Programming Language. As significant differences
exist, the complete license should be read.
PREAMBLE

View File

@ -1,11 +1,9 @@
The OpenLDAP Public License
Version 1.4, 18 January 1999
Copyright 1998-1999, The OpenLDAP Foundation. All Rights Reserved. Note: This
license is derived from the "Artistic License" as distributed with the Perl
Programming Language. As significant differences exist, the complete license
should be read.
Version 1.4, 18 January 1999 Copyright 1998-1999, The OpenLDAP Foundation.
All Rights Reserved. Note: This license is derived from the "Artistic License"
as distributed with the Perl Programming Language. As significant differences
exist, the complete license should be read.
PREAMBLE

Some files were not shown because too many files have changed in this diff Show More