Compare commits

...

61 Commits

Author SHA1 Message Date
6543
9749c35656 Changelog v1.12.0-rc2 (#11799)
* Update

* format

* seperate

* Update CHANGELOG.md

Co-authored-by: techknowlogick <matti@mdranta.net>

* Update CHANGELOG.md

Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>

Co-authored-by: techknowlogick <matti@mdranta.net>
Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
2020-06-08 09:42:17 +03:00
Cirno the Strongest
fc15e59475 Make tabular menu styling consistent for arc-green (#11570) (#11798)
* Make tabular menu styling consistent for arc-green

* rework completely

* transparent borders

* use darker color for active item; override only colors for borders

* Update web_src/less/themes/theme-arc-green.less

Co-authored-by: silverwind <me@silverwind.io>

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: zeripath <art27@cantab.net>
(cherry picked from commit 4395c607ed)
2020-06-07 18:27:31 -04:00
6543
78f0b5b92b Add option to API to update PullRequest base branch (#11666) (#11796)
* EditPull: add option to change base

Close #11552

Co-authored-by: Lauris BH <lauris@nix.lv>
2020-06-07 23:20:53 +03:00
6543
20951c5c21 In File Create/Update API return 404 if Branch does not exist (#11791) (#11795)
* In File Create/Update API return 404 if Branch does not exist (#11791)

* v1.12 version ;)
2020-06-07 22:50:19 +03:00
赵智超
99f7ec8f45 Fix doer of rename repo (#11789) (#11794)
fix #11725

Signed-off-by: a1012112796 <1012112796@qq.com>

Co-authored-by: zeripath <art27@cantab.net>

Co-authored-by: zeripath <art27@cantab.net>
2020-06-07 19:55:50 +03:00
Cirno the Strongest
a076cb2a4c Increase maximum SQLite variables count to 32766 (#11696) (#11783)
* Increase maximum SQLite variables count to 32766 (#11696)

per https://www.sqlite.org/limits.html

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
(cherry picked from commit a5aa5c58c1)

* Fix missing CGO_EXTRA_FLAGS build arg for docker

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-06-07 00:04:00 -04:00
zeripath
530ae650f3 Initialize SimpleMDE when making a code comment (#11749) (#11785)
Backport #11749

Fix #11704

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-Authored-By: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com>

Co-authored-by: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-06-06 20:11:51 -04:00
赵智超
821570c0b0 Fix to allow comment poster to edit or delete his own comments (#11671) (#11774)
* bug: fix comment update permision check

No the ui only allow poster to update or delet comment, which
is not reasonable and different with handle logic, this pr
change it to allow poster of comment do it

ref code:
e8955173a9/routers/repo/issue.go (L1636)

e8955173a9/routers/repo/issue.go (L1681)

fix #11663

Signed-off-by: a1012112796 <1012112796@qq.com>

* simplify code

* fix sign in

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: Lauris BH <lauris@nix.lv>

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: Lauris BH <lauris@nix.lv>
2020-06-06 17:43:01 -04:00
Cirno the Strongest
287e2c781b Fix timezone on issue deadline (#11697) (#11784)
* Fix timezone on issue deadline

* FormatDate

Co-authored-by: zeripath <art27@cantab.net>
(cherry picked from commit bbe13b60cd)
2020-06-06 13:44:16 +01:00
Emanuel Angelo
921a5c0b62 European Portuguese translation (#11568) (#11778)
This PR includes the modifications necessary to make use of the European Portuguese translation from the default setting.

Co-authored-by: zeripath <art27@cantab.net>
2020-06-06 10:41:06 +01:00
mrsdizzie
0ad4083cba Update emoji dataset with skin tone variants (#11678) (#11763)
* Update emoji dataset with skin tone variants

Since the format of emoji that support skin tone modifiers is predictable we can add different variants into our dataset when generating it so that we can match and properly style most skin tone variants of emoji. No real code change here other than what generates the dataset and the data itself.

* use escape unicode sequence in map

Co-authored-by: techknowlogick <techknowlogick@gitea.io>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-06-04 15:56:28 -03:00
6543
99058de553 [API] on 500 error only show message if gitea in dev mode (#11641) (#11753)
* add API specific InternalServerError()

* return 500 error msg only if not Production mode

* rm unnessesary change
2020-06-03 22:24:47 -04:00
S7evinK
fb155b8fa3 Add missing templates (#11729) (#11748)
Signed-off-by: Till Faelligen <tfaelligen@gmail.com>
2020-06-03 19:23:45 +01:00
zeripath
7dd9506d06 Fix verification of subkeys of default gpg key (#11713) (#11747)
* Fix verification of subkeys of default gpg key

Fix #10309

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Remove debug log

* Update models/gpg_key.go

* As per @6543

Signed-off-by: Andrew Thornton <art27@cantab.net>
2020-06-03 18:01:32 +01:00
Cirno the Strongest
f428d40822 Fix styling for commiter on diff view (#11715) (#11744)
* Fix styling for commiter on diff view

* Update options/locale/locale_en-US.ini

* Update templates/repo/commit_page.tmpl

Co-authored-by: silverwind <me@silverwind.io>

* Update templates/repo/commit_page.tmpl

Co-authored-by: silverwind <me@silverwind.io>

* Apply suggestions from code review

Co-authored-by: silverwind <me@silverwind.io>

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
(cherry picked from commit 8e035f81c0)
2020-06-03 09:29:19 +01:00
zeripath
7339018c5e Properly truncate system notices (#11714) (#11742)
Backport #11714

* Properly truncate system notices

As noted in #11658 the system notifications list will always suffix
system notices with ... even when the notice is longer than 120
characters.

Instead we should use .text.truncate to auto truncate and make the
notices clickable to view their details.

Signed-off-by: Andrew Thornton <art27@cantab.net>

* As per @CirnoT make table cell clickable

* ensure that pre wraps

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-06-03 02:44:05 +03:00
Lauris BH
a34826b19f Change language statistics to save size instead of percentage (#11681) (#11690)
* Change language statistics to save size instead of percentage (#11681)

* Change language statistics to save size instead of percentage in database

Co-Authored-By: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com>

* Do not exclude if only language

* Fix edge cases with special langauges

Co-authored-by: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com>

* Fix language stat calculation (#11692)

* Fix language stat calculation

* Group languages and ignore 0 size files

* remove unneeded code

Co-authored-by: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com>
2020-06-02 20:55:21 +03:00
6543
70739c32a9 Handle expected errors in FileCreate & FileUpdate API (#11643) (#11718)
as title

needed for #11641
2020-06-01 07:28:52 +01:00
guillep2k
249e22bb98 Add changelog for 1.11.6 (#11695) (#11701)
* Add changelog for 1.11.6

* Update CHANGELOG.md

Co-authored-by: techknowlogick <matti@mdranta.net>

* Update CHANGELOG.md

Co-authored-by: techknowlogick <matti@mdranta.net>

* Apply suggestions from @lafriks

* #11459 is bugfix

Co-authored-by: Guillermo Prandi <guillep2k@users.noreply.github.com>
Co-authored-by: techknowlogick <matti@mdranta.net>

Co-authored-by: Guillermo Prandi <guillep2k@users.noreply.github.com>
Co-authored-by: techknowlogick <matti@mdranta.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-05-31 01:28:42 -04:00
zeripath
d78c31c216 Add logging to long migrations (#11647) (#11691)
* Add logging to long migrations

Also fix v136 to not use models

Signed-off-by: Andrew Thornton <art27@cantab.net>
2020-05-30 21:44:14 -04:00
mrsdizzie
795b6865af Fix alignment for commits on dashboard (#11595) (#11680)
Fix alignment issue between commit SHA and commit message
2020-05-30 11:20:02 +03:00
mrsdizzie
0e44fab5d6 Update emoji regex (#11584) (#11679)
When matching emoji, use a regex built from the data we have instead of something generic using unicode ranges. A generic regex can't tell the difference between two separate emoji next to each other or one emoji that is built out of two separate emoji next to each other.

This means that emoji that are next to each other without space in between will be now accurately spanned individually with proper title etc...
2020-05-29 22:12:53 +01:00
Cirno the Strongest
6ad0d0a1b9 Fix missing authorization check on pull for public repos of private/limited org (#11656) (#11682)
Fixes #11651

(cherry picked from commit 02fa329a7c)
2020-05-29 16:00:22 -04:00
6543
d9db28a25a Doctor check & fix db consistency (#11111) (#11676)
needed to fix issue as described in #10280

* rename check-db to check-db-version
* add check-db-consistency:
* find issues without existing repository
* find pulls without existing issues
* find tracked times without existing issues/pulls
* find labels without repository or org reference

Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>

Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2020-05-29 13:00:43 -05:00
zeripath
5911e129a8 Default MSSQL port 0 to allow automatic detection by default (#11642) (#11673)
Backport #11642

Fix #11633

Signed-off-by: Andrew Thornton <art27@cantab.net>
2020-05-29 16:28:37 +03:00
Lauris BH
42f0769e30 Exclude generated files from language statistics (#11653) (#11670)
* Update go-enry to v2.5.2
2020-05-29 10:02:00 +01:00
zeripath
0c40b0badd Use -1 to disable key algorithm type in ssh.minimum_key_sizes (#11635) (#11662)
Backport #11635

Fix #11634

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-05-28 19:05:16 -04:00
6543
762c0463f4 Handle expected errors in AddGPGkey API (#11644) (#11661)
* handle GPG Parse & Email Errors

* correct TEST

* update Swagger

* more Docu
2020-05-28 18:16:41 -04:00
6543
bf1dbd7c56 Return json on 500 error from API (#11574) (#11659)
Backport #11574

add API specific InternalServerError()

InternalServerError
2020-05-28 19:27:51 +01:00
guillep2k
600bb545f3 When must change password only show Signout (#11600) (#11637)
When "Must Change Password" simplify the navbar header to only show the
signout button as all other links will redirect back. This prevents the
notifications icon from showing preventing initialization of the
event-source and hence preventing redirect_to being set, however in
addition do not set the redirect_to cookie if we are looking at the
/user/events page.

Fix #11554

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: zeripath <art27@cantab.net>
2020-05-27 08:08:14 +01:00
Cirno the Strongest
5331af1854 Backport various styling fixes (#11619)
* Fix inconsistent font size for markdown preview on new PR view (#11565)

We use same method for new issue form and issue view, but was missing from new PR view making it one place where markdown preview is inconsistent in font size.

(cherry picked from commit 04afd9d1e2)

* Fix margin on PR form (#11566)

(cherry picked from commit f2a0be1683)

* Fix margin for attached top header on code review (#11571)

Introduced naively by #11463

The margin was being applied too widely.

(cherry picked from commit e682a92295)

* Fix styling for PR merge section when no checks (#11609)

Makes styling consistent between two cases. Also removed unnecessary double border.

* Normalize avatar radius
2020-05-25 22:33:57 -04:00
Gary Kim
eb5ea5f67a Fix wrong milestone in webhook message (#11596) (#11611)
Backport of #11596

Signed-off-by: Gary Kim <gary@garykim.dev>

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-05-25 01:01:49 -04:00
zeripath
5e3dd3fafe When initialising repositories ensure that the user doing the creation is the initializer (#11601) (#11608)
Backport #11601

Fix #10760

Signed-off-by: Andrew Thornton <art27@cantab.net>
2020-05-25 00:24:49 -04:00
silverwind
339f5bb397 Fix serviceworker output file and misc improvements (#11562) (#11610)
* Fix serviceworker output file and misc improvements

- Fix output file location for production build
- Cache more asset types: fonts and worker variants
- Parallelize a few tasks during initalization
- Only invalidate caches starting with our prefix
- Remove public/serviceworker.js before building
- Remove font preloads, they cause strange cors issues
- Misc eslint config adjustments

* remove webpack output files on watch-frontend
2020-05-25 00:12:02 +03:00
zeripath
1ae5435e41 Prevent (caught) panic on login (#11590) (#11597)
Backport #11590

Unfortunately when the virtual session is released it requires that the
real session does not exist. This worked fine when sessions were only
saved at the end of request/response cycle however, now sessions are
saved proactively this does not hold.

The result is a caught panic in the logs during every log-in.  This
panic has no significant side-effects but should not occur.

This PR marks the virtual session as released when released and updates
it if the same session is released again.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2020-05-24 18:12:25 +01:00
zeripath
ca61046f9f Prevent empty query parameter being set on dashboard (#11561) (#11604)
Prevent the dashboard from setting an empty query parameter

Fix #11543

Signed-off-by: Andrew Thornton art27@cantab.net
2020-05-24 17:20:09 +03:00
mrsdizzie
29368309ce Fix images in wiki edit preview (#11546) (#11602)
Make sure wiki editor sets wiki to true so gitea renders it as a wiki page.

Also change the context data attr for edit form. This looks wrong but everywhere else in our code assumes the urlPrefix to be just the repo url when rendering and manually adds /wiki to the rendered url regardless.

Fixes #11540
2020-05-24 14:01:10 +01:00
zeripath
a777f8ae75 Allow different HardBreaks settings for documents and comments (#11515) (#11599)
GH has different HardBreaks behaviour for markdown comments and documents.

Comments have hard breaks and documents have soft breaks - therefore Gitea's rendering will always be different from GH's if we only provide one setting.

Here we split the setting in to two - one for documents and one for comments and other things.

Signed-off-by: Andrew Thornton art27@cantab.net

Changes to index.js as per @silverwind 
Co-authored-by: silverwind <me@silverwind.io>

Changes to docs as per @guillep2k 
Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
2020-05-24 11:45:56 +01:00
Cirno the Strongest
80853a2238 Enforce transparent background on editor toolbar elements (#11569) (#11583)
Co-authored-by: Lauris BH <lauris@nix.lv>
(cherry picked from commit 38c773d8a5)

Co-authored-by: zeripath <art27@cantab.net>
2020-05-23 19:36:24 -04:00
zeripath
ce958f45cd Ensure serviceworker is created as /serviceworker.js (#11577) (#11582)
#11538 moved the serviceworker to webbox but unfortunately
created the serviceworker in public/js rather than public/

This PR fixes this, fixing multiple issues with broken js
as a result of that change.

Signed-off-by: Andrew Thornton art27@cantab.net
2020-05-23 21:41:33 +01:00
guillep2k
3b1e114ede Prevent transferring repos to invisible orgs (#11517) (#11549)
Co-authored-by: Guillermo Prandi <guillep2k@users.noreply.github.com>

Co-authored-by: Guillermo Prandi <guillep2k@users.noreply.github.com>
Co-authored-by: zeripath <art27@cantab.net>
2020-05-22 22:12:20 -04:00
silverwind
573a9c6228 Fix webpack chunk loading with STATIC_URL_PREFIX (#11526) (#11542)
Previously, we had only set __webpack_public_path__ to a path which
caused webpack chunks to be loaded from the current origin which is
incorrect when STATIC_URL_PREFIX points to another origin.

This should fix the issue curretnly seen on gitea.com.
2020-05-22 20:18:44 +01:00
silverwind
d131d53cbb Close EventSource before unloading the page (#11539) (#11557)
Should eliminate a error in the Firefox console regarding the connection
being interrupted while the page was loading.
2020-05-22 19:30:30 +01:00
L0veSunshine
2a6e6bf0f1 Fix the bug that the emoji don't disappear(#11489) (#11530)
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-05-22 12:36:25 -04:00
silverwind
655def5141 Move serviceworker to workbox and fix SSE interference (#11538) (#11547)
* Move serviceworker to workbox and fix SSE interference

Instead of statically hardcoding every frontend asset, this uses a
type-based approach to cache all js,css and manifest.json requests.

This also fixes the issue that the service worker was interfering with
EventSource because it was unconditionally handling all requests which
this new implementation doesn't.

Fixes: https://github.com/go-gitea/gitea/issues/11092
Fixes: https://github.com/go-gitea/gitea/issues/7372

* rethrow error instead of logging

* await .register

* Revert "rethrow error instead of logging"

This reverts commit 043162ba1f.

* improve comment

* remove JSRenderer

* add version-based cache invalidation

* refactor

* more refactor

* remove comment

* rename item to fit cache name

Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
2020-05-22 12:46:39 -03:00
silverwind
2042cf2cce Ensure emoji render with regular font-weight (#11541) (#11545)
Emoji characters don't support bold attributes and may do weird things
like rendering monochrome when bolded.
2020-05-22 11:57:13 +01:00
Matthew R. McDougal
7b438b3566 Fix form action template substitutions on admin pages (backport #11519) (#11531)
* Fix form action template substitution on admin dashboard

* Fix form action template substitution on admin monitoring page

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: Lauris BH <lauris@nix.lv>
2020-05-21 23:02:56 -04:00
zeripath
8bde2e9813 API PullReviewComment HTMLPullURL should return the HTMLURL (#11501) (#11533)
Fix #11499

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-05-21 19:35:19 +03:00
zeripath
8525a48581 Fix repo-list private and total count bugs (#11500) (#11532)
* Fix repo-list private and total count bugs

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Ensure limited and private org public repos are displayed on "private"

Signed-off-by: Andrew Thornton <art27@cantab.net>

* switch from onlyPrivate to is_private

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Generate swagger

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>

Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com>
2020-05-21 08:23:20 -05:00
Cirno the Strongest
034492384b Fix margin for branch-update grid on PR view when update button is not present (#11521) (#11525)
* Fix margin for branch-update grid on PR view when update button is not present

* Move padding to row element

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
(cherry picked from commit ee4e8542c7)

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-05-21 06:53:10 +01:00
zeripath
c83bc55b52 TrimSpace when reading InternalToken from a file (#11502) (#11524)
InternalTokens are fixed as alphanum strings therefore TrimSpace from these.
Also use isatty to not add a terminal newline when redirecting generate.

Fix #11498

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Lauris BH <lauris@nix.lv>

Co-authored-by: Lauris BH <lauris@nix.lv>
2020-05-20 15:42:03 -04:00
Cirno the Strongest
09cc6392f6 Fix selected line color in arc-green (#11492) (#11520)
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
(cherry picked from commit 6da87eda8b)
2020-05-20 19:15:34 +03:00
Cirno the Strongest
b67eafbc21 Use more toned colors for selected line (#11493) (#11511)
Co-authored-by: zeripath <art27@cantab.net>
(cherry picked from commit 7b66400f55)

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-05-19 22:50:48 -04:00
silverwind
c1ba480a7a Tweak reaction buttons (#11496) (#11516)
- Vertical centering using flexbox
- Very slightly decreased size of the boxes

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2020-05-19 18:02:25 -04:00
6543
1197512b2b Make localstorage read ssh or https correctly (#11483) (#11490)
* Make localstorage read ssh or https correctly

* Update index.js

If not login there is only a "https" button, This commit fix  the "https" button hasn't blue border.

* Keep user selected whether or not to log in

* Update index.js

Co-authored-by: L0veSunshine <xuan199651@gmail.com>
Co-authored-by: zeripath <art27@cantab.net>
2020-05-19 16:03:10 +03:00
Cirno the Strongest
1547ce5669 Fix top margin for bottom attached header (#11480) (#11485)
* Fix top margin for bottom attached header (#11480)

(cherry picked from commit 6b798feaf6)

* restart ci

Co-authored-by: Lauris BH <lauris@nix.lv>
2020-05-19 01:59:07 -04:00
Lauris BH
1aa6176bd8 MySQL instance is needed for all triggers (#11484) 2020-05-18 19:14:28 +03:00
Lauris BH
2289e59bd7 Changelog for v1.12.0-rc1 (#11462) 2020-05-18 16:04:04 +03:00
Lauris BH
6e75bc013e Fix comment box styling and cancelling (#11463) (#11464) (#11469) (#11467)
* Fix styling of resolved code comment box (#11463)

Co-authored-by: Lauris BH <lauris@nix.lv>

* Fix .comment-code-cloud not being removed when cancelling new code comment (#11464)

* Fix footer padding for comment code reply form on issue event view (#11469)

Co-authored-by: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com>
2020-05-18 10:17:35 +01:00
6543
087719cb8d Ensure public repositories in private organizations are visible and fix admin organizations list (#11465) (#11474)
* Ensure that we can see public repositories in private organization

Fix #10144 (Again)

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Fix Admin users and organizations page

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Update models/repo_list.go

Co-authored-by: Lauris BH <lauris@nix.lv>

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: Lauris BH <lauris@nix.lv>
2020-05-18 07:21:00 +01:00
6543
bbd9bebcc3 Fix "Unknown task: git_fsck" error on admin dashboard (#11468) (#11471)
* Fix "Unknown task: git_fsck" error on admin dashboard (#11468)

* Update .drone.yml

Co-authored-by: zeripath <art27@cantab.net>
2020-05-18 06:31:49 +01:00
130 changed files with 6374 additions and 3537 deletions

View File

@@ -105,12 +105,6 @@ services:
from_secret: gitlab_read_token
depends_on:
- build
when:
branch:
- master
event:
- push
- pull_request
- name: mysql8
pull: default

View File

@@ -25,7 +25,7 @@ globals:
Tribute: false
overrides:
- files: ["web_src/**/*.worker.js"]
- files: ["web_src/**/*.worker.js", "web_src/js/serviceworker.js"]
env:
worker: true
rules:
@@ -48,6 +48,7 @@ rules:
no-cond-assign: [2, except-parens]
no-console: [1, {allow: [info, warn, error]}]
no-continue: [0]
no-empty: [2, {allowEmptyCatch: true}]
no-eq-null: [2]
no-mixed-operators: [0]
no-multi-assign: [0]
@@ -57,6 +58,7 @@ rules:
no-restricted-syntax: [0]
no-return-await: [0]
no-shadow: [0]
no-underscore-dangle: [0]
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, ignoreRestSiblings: true}]
no-use-before-define: [0]
no-var: [2]

1
.gitignore vendored
View File

@@ -76,6 +76,7 @@ coverage.all
/node_modules
/yarn.lock
/public/js
/public/serviceworker.js
/public/css
/public/fonts
/public/fomantic

View File

@@ -4,6 +4,361 @@ 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.12.0-rc2](https://github.com/go-gitea/gitea/releases/tag/v1.12.0-rc2) - 2020-06-08
* BUGFIXES
* In File Create/Update API return 404 if Branch does not exist (#11791) (#11795)
* Fix doer of rename repo (#11789) (#11794)
* Initialize SimpleMDE when making a code comment (#11749) (#11785)
* Fix timezone on issue deadline (#11697) (#11784)
* Fix to allow comment poster to edit or delete his own comments (#11671) (#11774)
* Show full 500 error in API when Gitea in dev mode (#11641) (#11753)
* Add missing templates for Matrix system webhooks (#11729) (#11748)
* Fix verification of subkeys of default gpg key (#11713) (#11747)
* Fix styling for commiter on diff view (#11715) (#11744)
* Properly truncate system notices (#11714) (#11742)
* Handle expected errors in FileCreate & FileUpdate API (#11643) (#11718)
* Fix missing authorization check on pull for public repos of private/limited org (#11656) (#11682)
* Update emoji regex (#11584) (#11679)
* Doctor check & fix db consistency (#11111) (#11676)
* Default MSSQL port 0 to allow automatic detection by default (#11642) (#11673)
* Exclude generated files from language statistics (#11653) (#11670)
* Use -1 to disable key algorithm type in ssh.minimum_key_sizes (#11635) (#11662)
* Return json on 500 error from API (#11574) (#11659)
* When must change password only show Signout (#11600) (#11637)
* Backport various styling fixes (#11619)
* Fix wrong milestone in webhook message (#11596) (#11611)
* Fix serviceworker output file and misc improvements (#11562) (#11610)
* When initialising repositories ensure that the user doing the creation is the initializer (#11601) (#11608)
* Prevent empty query parameter being set on dashboard (#11561) (#11604)
* Fix images in wiki edit preview (#11546) (#11602)
* Allow different HardBreaks settings for documents and comments (#11515) (#11599)
* Prevent (caught) panic on login (#11590) (#11597)
* Prevent transferring repos to invisible orgs (#11517) (#11549)
* Move serviceworker to workbox and fix SSE interference (#11538) (#11547)
* API PullReviewComment HTMLPullURL should return the HTMLURL (#11501) (#11533)
* Fix repo-list private and total count bugs (#11500) (#11532)
* Fix form action template substitutions on admin pages (backport #11519) (#11531)
* Fix a bug where the reaction emoji doesn't disappear. (#11489) (#11530)
* TrimSpace when reading InternalToken from a file (#11502) (#11524)
* Fix selected line color in arc-green (#11492) (#11520)
* Make localstorage read ssh or https correctly (#11483) (#11490)
* ENHANCEMENTS
* Make tabular menu styling consistent for arc-green (#11570) (#11798)
* Add option to API to update PullRequest base branch (#11666) (#11796)
* Increase maximum SQLite variables count to 32766 (#11696) (#11783)
* Update emoji dataset with skin tone variants (#11678) (#11763)
* Add logging to long migrations (#11647) (#11691)
* Change language statistics to save size instead of percentage (#11681) (#11690)
* Fix alignment for commits on dashboard (#11595) (#11680)
* Handle expected errors in AddGPGkey API (#11644) (#11661)
* Close EventSource before unloading the page (#11539) (#11557)
* Ensure emoji render with regular font-weight (#11541) (#11545)
* Fix webpack chunk loading with STATIC_URL_PREFIX (#11526) (#11542)
* Tweak reaction buttons (#11516)
* Use more toned colors for selected line (#11493) (#11511)
## [1.12.0-rc1](https://github.com/go-gitea/gitea/releases/tag/v1.12.0-rc1) - 2020-05-18
* BREAKING
* When using API CreateRelease set created_unix to the tag commit time (#11218)
* Enable ENABLE_HARD_LINE_BREAK by default for rendering markdown (#11162)
* Fix sanitizer config - multiple rules (#11133)
* Remove check on username when using AccessToken authentication for the API (#11015)
* Return 404 from Contents API when items don't exist (#10323)
* Notification API should always return a JSON object with the current count of notifications (#10059)
* Remove migration support from versions earlier than 1.6.0 (#10026)
* FEATURES
* Improve config logging when WrappedQueue times out (#11174)
* Add branch delete to API (#11112)
* Use markdown frontmatter to provide Table of contents, language and frontmatter rendering (#11047)
* Add a way to mark Conversation (code comment) resolved (#11037)
* Handle yaml frontmatter in markdown (#11016)
* Cache PullRequest Divergence (#10914)
* Make `gitea admin auth list` formatting configurable (#10844)
* Add Matrix webhook (#10831)
* Add Organization Wide Labels (#10814)
* Allow to set protected file patterns for files that can not be changed under no conditions (#10806)
* Option to set default branch at repository creation (#10803)
* Add request review from specific reviewers feature in pull request (#10756)
* Add NextCloud oauth (#10562)
* System-wide webhooks (#10546)
* Relax sanitization as per https://github.com/jch/html-pipeline (#10527)
* Use media links for img in post-process (#10515)
* Add API endpoints to manage OAuth2 Application (list/create/delete) (#10437)
* Render READMEs in docs/ .gitea or .github from root (#10361)
* Add feishu webhook support (#10229)
* Cache last commit to accelerate the repository directory page visit (#10069)
* Implement basic app.ini and path checks to doctor cmd (#10064)
* Make WorkerPools and Queues flushable (#10001)
* Implement "embedded" command to extract static resources (#9982)
* Add API endpoint for repo transfer (#9947)
* Make archive prefixing configurable with a global setting (#9943)
* Add Unique Queue infrastructure and move TestPullRequests to this (#9856)
* Issue/PR Context Popups (#9822)
* Add "Update Branch" button to Pull Requests (#9784)
* Add require signed commit for protected branch (#9708)
* Mark PR reviews as stale at push and allow to dismiss stale approvals (#9532)
* Add API notification endpoints (#9488)
* Issue search support elasticsearch (#9428)
* Add API branch protection endpoint (#9311)
* Add a new command doctor to check if some wrong configurations on gitea instance (#9095)
* Add support for migrating from Gitlab (#9084)
* Add support for database schema in PostgreSQL (#8819)
* Add setting to set default and global disabled repository units. (#8788)
* Language statistics bar for repositories (#8037)
* Restricted users (#6274)
* BUGFIXES
* Check branch protection on IsUserAllowedToUpdate (#11448)
* Fix margin on attached segment headers when they are separated by other element (#11425)
* Fix webhook template when validation errors occur (#11421)
* Fix NPE in template due to missing signing key on commit page (#11392)
* Restore active background to Register button on Register page (#11390)
* Fix hook failure due to relative LFS_CONTENT_PATH (#11362)
* Correctly set the organization num repos (#11339)
* Prevent 500 with badly formed task list (#11328)
* Allow compare page to look up base, head, own-fork, forkbase-of-head (#11327)
* Handle panics that percolate up to the graceful module (#11291)
* Don't allow registration via the web form, when AllowOnlyExternalRegistration is True (#11248)
* Patch fomantic-ui to workaround build issue (#11244)
* Prevent panic during wrappedConn close at hammertime (#11219)
* On logout force redirect to start page (#11202)
* Fix creation of Organization repos by Users with max created personal repos (#11183)
* Add option to increase provided OAuth2 token maximum size (#11180)
* Log the indexer path on failure (#11172)
* Ensure that relative paths in edit preview work (#11143)
* Make API EditIssue and EditPullRequest issue notifications (#11123)
* Send 404 immediately for known public requests (#11117)
* Remove nil inserts in models (#11096)
* Add GetReviews() to RetryDownloader (#11093)
* Remove nonexistent serviceworker entries (#11091)
* Simplify and fix GetApprovalCounts (#11086)
* Fix wiki revision template and simplify some tmpl conditions (#11080)
* Make branch parameter optional for /api/v1/repos/{owner}/{repo}/contents/{filepath} (#11067)
* Align review-item svg octicons (#11065)
* Automatically remove Watches, Assignments, etc if user loses access due to being removed as collaborator or from a team (#10997)
* Users should not be able to prohibit their own login (#10970)
* Fix scrollbar issues in dropdowns (#10897)
* Change the order of issues.closed_by to list opening user first (#10876)
* Allow site admin to check /api/v1/orgs endpoints (#10867)
* Avoid logging []byte in queue failures - convert to string first (#10865)
* Use ErrKeyUnableToVerify if fail to calc fingerprint in ssh-keygen (#10863)
* Fix assignees double load bug (#10856)
* Handle push rejection in branch and upload (#10854)
* In authorized_keys use double-quote for windows compatibility (#10841)
* Fix milestone template (#10824)
* log.Fatal on failure to listen to SSH port (#10795)
* Fix forked repo has no icon and language stat. (#10791)
* Fix tag/release deletion (#10663)
* Fix webhook migration (#10641)
* Migration for deleting orphaned dependencies (#10617)
* Add migration to fix the old broken merge-bases (#10604)
* Update templates for Go 1.14 (#10596)
* Remove unnecessary parentheses in wiki/view template (#10583)
* Change default value of DefaultCommandExecutionTimeout to match docs (#10581)
* Handle panic in indexer initialisation better (#10534)
* Set correct content_type value for Gogs/Gitea webhooks (#9504) (#10456)
* Fixed wrong AppSubUrl in multiple templates (#10447)
* Fix profile page CSS (#10406)
* Inject SVG sprite via ajax (#10320)
* Fix migration information update bug when linked github account (#10310)
* Allow admin to check org membership by API for other users (#10201)
* Fix topics dropdown (#10167)
* Ensure DeleteUser is not allowed to Delete Orgs and visa versa (#10134)
* Fix IsErrPullClosed (#10093)
* Accept punctuation after simple+cross repository issue references (#10091)
* On merge of already closed PR redirect back to the pulls page (#10010)
* Fix crowdin update script (#9969)
* Fix pull view when head repository or head branch missed and close related pull requests when delete head repository or head branch (#9927)
* Add option to prevent LDAP from deactivating everything on empty search (#9879)
* Fix admin handling at merge of PR (#9749)
* err_admin_name_pattern_not_allowed String Clarification (#9731)
* Fix wrong original git service type on a migrated repository (#9693)
* Fix ref links in issue overviews for tags (#8742)
* ENHANCEMENTS
* Increase width for authors on commit view (#11441)
* Hide archived repos by default in repo-list (#11440)
* Better styling for code review comment textarea (#11428)
* Support view individual commit for wiki pages (#11415)
* Fix yellow background on active elements in code review (#11414)
* Better styling for code review comment form (#11413)
* Change install description on homepage (#11395)
* Ensure search action button is coalesced to adjacent input (#11385)
* Switch code editor to Monaco (#11366)
* Add paging and archive/private repository filtering to dashboard list (#11321)
* Changed image of openid-connect logo for better look on arc-green theme (#11312)
* Load Repo Topics on blame view too (#11307)
* Change the style in admin notice content view from `<p>` to `<pre>` (#11301)
* Allow log.xxx.default to set logging settings for the default logger only (#11292)
* Automatically attempt auto recovery of broken disk queues (Update lunny/levelqueue to 0.3.0) (#11285)
* Make sendmail a Process and have default timeout (#11256)
* Check value of skip-repository flag in dump command (#11254)
* Fix submit review form (#11252)
* Allow unauthenticated users to compare (#11240)
* Add EventSource support (#11235)
* Refactor Milestone related (#11225)
* Add pull review API endpoints (#11224)
* Add a 'this' to issue close/reopened messages (#11204)
* When migrating from Gitlab map Approvals to approving Reviews (#11147)
* Improve representation of attachments in issues (#11141)
* Protect default branch against deletion (#11115)
* Add X-Total-Count on /repos/{owner]/{repo}/pulls API endpoint (#11113)
* Fix status label on branches list vertical alignment (#11109)
* Add single release page and latest redirect (#11102)
* Add missing commit states to PR checks template (#11085)
* Change icon on title for merged PR to git-merge (#11064)
* Add MergePull comment type instead of close for merge PR (#11058)
* Upgrade jQuery to 3.5.0, remove jQuery-Migrate, fix deprecations (#11055)
* Consolidate author name across timeline (#11053)
* Refactor UpdateOAuth2Application (#11034)
* Support unicode emojis and remove emojify.js (#11032)
* Add git hook "warning" to admin panel (#11030)
* Add flash notify for email preference setting success (#11027)
* Remove package code.gitea.io/gitea/modules/git import out of models (#11025)
* Match arc-green code tag color to code blocks (#11023)
* Move syntax highlighting to web worker (#11017)
* Prevent merge of outdated PRs on protected branches (#11012)
* Add Get/Update for api/v1/user/applications/oauth2 (#11008)
* Upgrade to most recent bluemonday (#11007)
* Tweak code tags in markdown (#11000)
* Reject duplicate AccessToken names (#10994)
* Fix Ctrl-Enter shortcut for issues (#10986)
* Provide `OwnerName` field for README template (#10981)
* Prettify Timeline (#10972)
* Add issue subscription check to API (#10967)
* Use AJAX for notifications table (#10961)
* Adjust label padding (#10957)
* Avoiding directory execution on hook (#10954) (#10955)
* Migrate ActivityHeatmap to Vue SFC (#10953)
* Change merge strategy do not check write access if user in merge white list (#10951)
* Enable GO111MODULE=on globally in Makefile (#10939)
* API endpoint to get single commit via SHA and Ref (#10915)
* Add accordion to release list and hide non-latest (#10910)
* Split dashboard elements into separate template files (#10885)
* Add more message on sidebar menus (#10872)
* Set MySQL rowtype to dynamic for new tables (#10833)
* Completely fix task-list checkbox styling (#10798)
* Hide gear icon for user who can't use them on sidebar (#10750)
* Refactor Cron and merge dashboard tasks (#10745)
* Change review status icons on pr view style to github style (#10737)
* Make pagination optional for API list notification endpoints (#10714)
* Fix tab indentation in code view (#10671)
* Fix task-list checkbox styling (#10668)
* Multiple LFS improvements (#10667)
* Make PR message on pushes configurable (#10664)
* Move dropzone.js to npm/webpack (#10645)
* Ensure Update button is enabled even when CI has failed (#10640)
* Add restricted user filter to LDAP authentication (#10600)
* Add Yandex OAuth2 provider (#8335) (#10564)
* Make avatar lookup occur at image request (#10540)
* Prevent accidential selection of language stats bar (#10537)
* Add fluid-icon (#10491)
* Inform participants on UI too (#10473)
* Build with go 1.14 (and raise minimum go version to 1.12) (#10467)
* Add max-file-size to LFS (#10463)
* Enable paggination for ListRepoTags API (#10454)
* Update JS dependencies (#10450)
* Show the username as a fallback on feeds if full name is blank (#10438)
* Various dark theme fixes (#10416)
* Display pull request head branch even the branch deleted or repository deleted (#10413)
* Prevent Firefox from using apple-touch-icon (#10402)
* Fix input[type=file] on dark theme (#10382)
* Improve mobile review-box sizing (#10297)
* Notification: queue ui.go notification-service (#10281)
* Add detected file language to code search (#10256)
* Index code and stats only for non-empty repositories (#10251)
* Add Approval Counts to pulls list (#10238)
* Limit label list height on edit issue page (#10216)
* Improve 404 error message (#10214)
* Tweak locale to respect singular conflicting file message in PR list (#10177)
* Fix commit view (#10169)
* Reorganize frontend files and tooling (#10168)
* Allow emoji on popup label (#10166)
* ListIssues add filter for milestones API (#10148)
* Show if a PR has conflicting files on the PR lists (#10130)
* Fix inconsistent label color format in API (#10129)
* Show download count info in release list (#10124)
* Add Octicon SVG spritemap (#10107)
* Update aria-fixed semantic-dropdown to fomantic master (#10096)
* Fix apple-touch-icon, regenerate images (#10065)(#10006)
* Style blockquote for default issue mail template (#10024)
* More expansions in template repositories (#10021)
* Allow list collaborators for users with Read access to repo (#9995)
* Add explicit dimensions to navbar avatar (#9986)
* Remove loadCSS and preload woff2 icon fonts (#9976)
* Fix commit view JS features, reimplement folding (#9968)
* Fix review avatar image (#9962)
* Improve notification pager (#9821)
* Move jquery and jquery-migrate to npm/webpack (#9813)
* Change font to Roboto to support more charsets (#9803)
* Move mailer to use a queue (#9789)
* Issue search on my related repositories (#9758)
* Add "before" query to ListIssueComments and ListRepoIssueComments API (#9685)
* Move tracked time api convert to convert package (#9665)
* Improve PR info in default merge message (#9635)
* Granular webhook events (#9626)
* Add Reviewed-on in commit message (#9623)
* Add top author stats to activity page (#9615)
* Allow repo admin to merge PR regardless of review status (#9611)
* Migrate reactions when migrating repository from github (#9599)
* API orgEditTeam make Fields optional (#9556)
* Move create/fork repository from models to modules/repository (#9489)
* Migrate reviews when migrating repository from github (#9463)
* Times API add filters (#9373)
* Move push commits from models to modules/repository (#9370)
* Add API endpoint to check notifications [Extend #9488] (#9595)
* Add GET /orgs API endpoint (#9560)
* API add/generalize pagination (#9452)
* Make create org repo API call same as github (#9186)
* BUILD
* Turn off go modules for xgo and gxz (#10963)
* Add gitea-vet (#10948)
* Rename scripts to build and add revive command as a new build tool command (#10942)
* Add 'make lint', restructure 'compliance' pipeline (#10861)
* Move JS build dependencies to 'dependencies' (#10763)
* Use whitelist to find go files, run find only once (#10594)
* Move vue and vue-calendar-heatmap to npm/webpack (#10188)
* Move jquery.are-you-sure to npm/webpack (#10063)
* Move highlight.js to npm/webpack (#10011)
* Generate Bindata if TAGS="bindata" and not up-to-date (#10004)
* Move CSS build to webpack (#9983)
* Move fomantic target, update 'make help' (#9945)
* Add css extraction and minification to webpack (#9944)
* Misc webpack tweaks (#9924)
* Make node_modules a order-only prerequisite (#9923)
* Update documentation for the go module era (#9751)
* Move swagger-ui to webpack/npm and update it to 3.24.3 (#9714)
* Use npm to manage fomantic and only build needed components (#9561)
* MISC
* Add gnupg to Dockerfile (#11365)
* Update snapcraft.yaml for core18 and latest features (#11300)
* Update JS dependencies, min Node.js version 10.13 (#11246)
* Change default charset for MySQL on install to utf8mb4 (#10989)
* Return issue subscription status from API subscribe (#10966)
* Fix queue log param (#10733)
* Add warning when using relative path to app.ini (#10104)
## [1.11.6](https://github.com/go-gitea/gitea/releases/tag/v1.11.6) - 2020-05-30
* SECURITY
* Fix missing authorization check on pull for public repos of private/limited org (#11656) (#11683)
* Use session for retrieving org teams (#11438) (#11439)
* BUGFIXES
* Return json on 500 error from API (#11574) (#11660)
* Fix wrong milestone in webhook message (#11596) (#11612)
* Prevent (caught) panic on login (#11590) (#11598)
* Fix commit page js error (#11527)
* Use media links for img in post-process (#10515) (#11504)
* Ensure public repositories in private organizations are visible and fix admin organizations list (#11465) (#11475)
* Set correct Content-Type value for Gogs/Gitea webhooks (#9504) (#10456) (#11461)
* Allow all members of private orgs to see public repos (#11442) (#11459)
* Whenever the ctx.Session is updated, release it to save it before sending the redirect (#11456) (#11457)
* Forcibly clean and destroy the session on logout (#11447) (#11451)
* Fix /api/v1/orgs/* endpoints by changing parameter to :org from :orgname (#11381)
* Add tracked time fix to doctor (part of #11111) (#11138)
* Fix webpack chunk loading with STATIC_URL_PREFIX (#11526) (#11544)
* Remove unnecessary parentheses in wiki/revision.tmpl to allow 1.11 to build on go1.14 (#11481)
## [1.11.5](https://github.com/go-gitea/gitea/releases/tag/v1.11.5) - 2020-05-09
* BUGFIXES

View File

@@ -9,6 +9,7 @@ ENV GOPROXY ${GOPROXY:-direct}
ARG GITEA_VERSION
ARG TAGS="sqlite sqlite_unlock_notify"
ENV TAGS "bindata $TAGS"
ARG CGO_EXTRA_CFLAGS
#Build deps
RUN apk --no-cache add build-base git nodejs npm

View File

@@ -33,6 +33,9 @@ MIN_NODE_VERSION := 010013000
ifeq ($(HAS_GO), GO)
GOPATH ?= $(shell $(GO) env GOPATH)
export PATH := $(GOPATH)/bin:$(PATH)
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS)
endif
@@ -88,7 +91,7 @@ GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(fi
WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f)
WEBPACK_CONFIGS := webpack.config.js
WEBPACK_DEST := public/js/index.js public/css/index.css
WEBPACK_DEST_DIRS := public/js public/css public/fonts
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/serviceworker.js
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
@@ -194,7 +197,7 @@ node-check:
.PHONY: clean-all
clean-all: clean
rm -rf $(WEBPACK_DEST_DIRS) $(FOMANTIC_DEST_DIR)
rm -rf $(WEBPACK_DEST_ENTRIES) $(FOMANTIC_DEST_DIR)
.PHONY: clean
clean:
@@ -295,6 +298,7 @@ lint-frontend: node_modules
.PHONY: watch-frontend
watch-frontend: node_modules
rm -rf $(WEBPACK_DEST_ENTRIES)
NODE_ENV=development npx webpack --hide-modules --display-entrypoints=false --watch --progress
.PHONY: test
@@ -498,7 +502,7 @@ check: test
.PHONY: install $(TAGS_PREREQ)
install: $(wildcard *.go)
$(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
.PHONY: build
build: frontend backend
@@ -514,7 +518,7 @@ generate: $(TAGS_PREREQ)
CC= GOOS= GOARCH= $(GO) generate -mod=vendor -tags '$(TAGS)' $(GO_PACKAGES)
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
$(GO) build -mod=vendor $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build -mod=vendor $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
.PHONY: release
release: frontend generate release-windows release-linux release-darwin release-copy release-compress release-sources release-check
@@ -527,7 +531,7 @@ release-windows: | $(DIST_DIRS)
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u src.techknowlogick.com/xgo; \
fi
GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
CGO_CFLAGS="$(CGO_CFLAGS)" GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
ifeq ($(CI),drone)
cp /build/* $(DIST)/binaries
endif
@@ -537,7 +541,7 @@ release-linux: | $(DIST_DIRS)
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u src.techknowlogick.com/xgo; \
fi
GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/mips64le,linux/mips,linux/mipsle' -out gitea-$(VERSION) .
CGO_CFLAGS="$(CGO_CFLAGS)" GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/mips64le,linux/mips,linux/mipsle' -out gitea-$(VERSION) .
ifeq ($(CI),drone)
cp /build/* $(DIST)/binaries
endif
@@ -547,7 +551,7 @@ release-darwin: | $(DIST_DIRS)
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u src.techknowlogick.com/xgo; \
fi
GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gitea-$(VERSION) .
CGO_CFLAGS="$(CGO_CFLAGS)" GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gitea-$(VERSION) .
ifeq ($(CI),drone)
cp /build/* $(DIST)/binaries
endif
@@ -598,7 +602,7 @@ $(FOMANTIC_DEST): $(FOMANTIC_CONFIGS) package-lock.json | node_modules
webpack: $(WEBPACK_DEST)
$(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json | node_modules
rm -rf $(WEBPACK_DEST_DIRS)
rm -rf $(WEBPACK_DEST_ENTRIES)
npx webpack --hide-modules --display-entrypoints=false
@touch $(WEBPACK_DEST)

File diff suppressed because one or more lines are too long

View File

@@ -19,6 +19,7 @@ import (
"sort"
"strconv"
"strings"
"unicode/utf8"
)
const (
@@ -39,6 +40,7 @@ type Emoji struct {
Description string `json:"description,omitempty"`
Aliases []string `json:"aliases"`
UnicodeVersion string `json:"unicode_version,omitempty"`
SkinTones bool `json:"skin_tones,omitempty"`
}
// Don't include some fields in JSON
@@ -47,6 +49,7 @@ func (e Emoji) MarshalJSON() ([]byte, error) {
x := emoji(e)
x.UnicodeVersion = ""
x.Description = ""
x.SkinTones = false
return json.Marshal(x)
}
@@ -75,6 +78,7 @@ var replacer = strings.NewReplacer(
", Description:", ", ",
", Aliases:", ", ",
", UnicodeVersion:", ", ",
", SkinTones:", ", ",
)
var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
@@ -102,18 +106,20 @@ func generate() ([]byte, error) {
return nil, err
}
var re = regexp.MustCompile(`keycap|registered|copyright`)
tmp := data[:0]
var skinTones = make(map[string]string)
// filter out emoji that require greater than max unicode version
skinTones["\U0001f3fb"] = "Light Skin Tone"
skinTones["\U0001f3fc"] = "Medium-Light Skin Tone"
skinTones["\U0001f3fd"] = "Medium Skin Tone"
skinTones["\U0001f3fe"] = "Medium-Dark Skin Tone"
skinTones["\U0001f3ff"] = "Dark Skin Tone"
var tmp Gemoji
//filter out emoji that require greater than max unicode version
for i := range data {
val, _ := strconv.ParseFloat(data[i].UnicodeVersion, 64)
if int(val) <= maxUnicodeVersion {
// remove these keycaps for now they really complicate matching since
// they include normal letters in them
if re.MatchString(data[i].Description) {
continue
}
tmp = append(tmp, data[i])
}
}
@@ -123,7 +129,6 @@ func generate() ([]byte, error) {
return data[i].Aliases[0] < data[j].Aliases[0]
})
aliasPairs := make([]string, 0)
aliasMap := make(map[string]int, len(data))
for i, e := range data {
@@ -135,7 +140,6 @@ func generate() ([]byte, error) {
continue
}
aliasMap[a] = i
aliasPairs = append(aliasPairs, ":"+a+":", e.Emoji)
}
}
@@ -149,6 +153,43 @@ func generate() ([]byte, error) {
data[i].Aliases = append(data[i].Aliases, "laugh")
}
// write a JSON file to use with tribute (write before adding skin tones since we can't support them there yet)
file, _ := json.Marshal(data)
_ = ioutil.WriteFile("assets/emoji.json", file, 0644)
// Add skin tones to emoji that support it
var (
s []string
newEmoji string
newDescription string
newData Emoji
)
for i := range data {
if data[i].SkinTones {
for k, v := range skinTones {
s = strings.Split(data[i].Emoji, "")
if utf8.RuneCountInString(data[i].Emoji) == 1 {
s = append(s, k)
} else {
// insert into slice after first element because all emoji that support skin tones
// have that modifer placed at this spot
s = append(s, "")
copy(s[2:], s[1:])
s[1] = k
}
newEmoji = strings.Join(s, "")
newDescription = data[i].Description + ": " + v
newAlias := data[i].Aliases[0] + "_" + strings.ReplaceAll(v, " ", "_")
newData = Emoji{newEmoji, newDescription, []string{newAlias}, "12.0", false}
data = append(data, newData)
}
}
}
// add header
str := replacer.Replace(fmt.Sprintf(hdr, gemojiURL, data))
@@ -162,10 +203,6 @@ func generate() ([]byte, error) {
return "{" + strconv.QuoteToASCII(s)
})
// write a JSON file to use with tribute
file, _ := json.Marshal(data)
_ = ioutil.WriteFile("assets/emoji.json", file, 0644)
// format
return format.Source([]byte(str))
}

View File

@@ -85,10 +85,16 @@ var checklist = []check{
},
{
title: "Check Database Version",
name: "check-db",
name: "check-db-version",
isDefault: true,
f: runDoctorCheckDBVersion,
abortIfFailed: true,
abortIfFailed: false,
},
{
title: "Check consistency of database",
name: "check-db-consistency",
isDefault: false,
f: runDoctorCheckDBConsistency,
},
{
title: "Check if OpenSSH authorized_keys file is up-to-date",
@@ -495,3 +501,80 @@ func runDoctorScriptType(ctx *cli.Context) ([]string, error) {
}
return []string{fmt.Sprintf("ScriptType %s is on the current PATH at %s", setting.ScriptType, path)}, nil
}
func runDoctorCheckDBConsistency(ctx *cli.Context) ([]string, error) {
var results []string
// make sure DB version is uptodate
if err := models.NewEngine(context.Background(), migrations.EnsureUpToDate); err != nil {
return nil, fmt.Errorf("model version on the database does not match the current Gitea version. Model consistency will not be checked until the database is upgraded")
}
//find labels without existing repo or org
count, err := models.CountOrphanedLabels()
if err != nil {
return nil, err
}
if count > 0 {
if ctx.Bool("fix") {
if err = models.DeleteOrphanedLabels(); err != nil {
return nil, err
}
results = append(results, fmt.Sprintf("%d labels without existing repository/organisation deleted", count))
} else {
results = append(results, fmt.Sprintf("%d labels without existing repository/organisation", count))
}
}
//find issues without existing repository
count, err = models.CountOrphanedIssues()
if err != nil {
return nil, err
}
if count > 0 {
if ctx.Bool("fix") {
if err = models.DeleteOrphanedIssues(); err != nil {
return nil, err
}
results = append(results, fmt.Sprintf("%d issues without existing repository deleted", count))
} else {
results = append(results, fmt.Sprintf("%d issues without existing repository", count))
}
}
//find pulls without existing issues
count, err = models.CountOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id")
if err != nil {
return nil, err
}
if count > 0 {
if ctx.Bool("fix") {
if err = models.DeleteOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id"); err != nil {
return nil, err
}
results = append(results, fmt.Sprintf("%d pull requests without existing issue deleted", count))
} else {
results = append(results, fmt.Sprintf("%d pull requests without existing issue", count))
}
}
//find tracked times without existing issues/pulls
count, err = models.CountOrphanedObjects("tracked_time", "issue", "tracked_time.issue_id=issue.id")
if err != nil {
return nil, err
}
if count > 0 {
if ctx.Bool("fix") {
if err = models.DeleteOrphanedObjects("tracked_time", "issue", "tracked_time.issue_id=issue.id"); err != nil {
return nil, err
}
results = append(results, fmt.Sprintf("%d tracked times without existing issue deleted", count))
} else {
results = append(results, fmt.Sprintf("%d tracked times without existing issue", count))
}
}
//ToDo: function to recalc all counters
return results, nil
}

View File

@@ -7,9 +7,11 @@ package cmd
import (
"fmt"
"os"
"code.gitea.io/gitea/modules/generate"
"github.com/mattn/go-isatty"
"github.com/urfave/cli"
)
@@ -59,7 +61,12 @@ func runGenerateInternalToken(c *cli.Context) error {
return err
}
fmt.Printf("%s\n", internalToken)
fmt.Printf("%s", internalToken)
if isatty.IsTerminal(os.Stdout.Fd()) {
fmt.Printf("\n")
}
return nil
}
@@ -69,7 +76,12 @@ func runGenerateLfsJwtSecret(c *cli.Context) error {
return err
}
fmt.Printf("%s\n", JWTSecretBase64)
fmt.Printf("%s", JWTSecretBase64)
if isatty.IsTerminal(os.Stdout.Fd()) {
fmt.Printf("\n")
}
return nil
}
@@ -79,6 +91,11 @@ func runGenerateSecretKey(c *cli.Context) error {
return err
}
fmt.Printf("%s\n", secretKey)
fmt.Printf("%s", secretKey)
if isatty.IsTerminal(os.Stdout.Fd()) {
fmt.Printf("\n")
}
return nil
}

View File

@@ -216,7 +216,10 @@ EVENT_SOURCE_UPDATE_TIME = 10s
; Render soft line breaks as hard line breaks, which means a single newline character between
; paragraphs will cause a line break and adding trailing whitespace to paragraphs is not
; necessary to force a line break.
ENABLE_HARD_LINE_BREAK = true
; Render soft line breaks as hard line breaks for comments
ENABLE_HARD_LINE_BREAK_IN_COMMENTS = true
; Render soft line breaks as hard line breaks for markdown documents
ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS = false
; Comma separated list of custom URL-Schemes that are allowed as links when rendering Markdown
; for example git,magnet,ftp (more at https://en.wikipedia.org/wiki/List_of_URI_schemes)
; URLs starting with http and https are always displayed, whatever is put in this entry.
@@ -934,8 +937,8 @@ JWT_SECRET=Bk0yK7Y9g_p56v86KaHqjSbxvNvu3SbKoOdOt2ZcXvU
MAX_TOKEN_LENGTH=32767
[i18n]
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR
NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,Українська,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR
NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,Українська,日本語,español,português do Brasil,Português de Portugal,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어
; Used for datetimepicker
[i18n.datelang]
@@ -952,6 +955,7 @@ uk-UA = uk
ja-JP = ja
es-ES = es
pt-BR = pt-BR
pt-PT = pt
pl-PL = pl
bg-BG = bg
it-IT = it

2
docker/Makefile vendored
View File

@@ -11,4 +11,4 @@ docker:
.PHONY: docker-build
docker-build:
docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" LDFLAGS="$(LDFLAGS)" webhippie/golang:edge make clean build
docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" LDFLAGS="$(LDFLAGS)" CGO_EXTRA_CFLAGS="$(CGO_EXTRA_CFLAGS)" webhippie/golang:edge make clean build

View File

@@ -312,3 +312,50 @@ languages:
url: https://discourse.gitea.io/
weight: 80
pre: group
pt-pt:
weight: 6
languageName: Português de Portugal
menu:
page:
- name: Página inicial
url: https://gitea.io/pt-pt/
weight: 10
pre: home
- name: Documentação
url: /pt-pt/
weight: 20
pre: question
post: active
- name: API
url: https://try.gitea.io/api/swagger
weight: 45
pre: plug
- name: Blog
url: https://blog.gitea.io/
weight: 30
pre: rss
- name: Código-fonte
url: https://code.gitea.io/
weight: 40
pre: code
- name: Tradução
url: https://crowdin.com/project/gitea
weight: 41
pre: language
- name: Descarregamentos
url: https://dl.gitea.io/
weight: 50
pre: download
- name: GitHub
url: https://github.com/go-gitea/
weight: 60
pre: github
- name: Discussão no Discord
url: https://discord.gg/Gitea
weight: 70
pre: comment
- name: Fórum
url: https://discourse.gitea.io/
weight: 80
pre: group

View File

@@ -152,7 +152,10 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
## Markdown (`markdown`)
- `ENABLE_HARD_LINE_BREAK`: **true**: Render soft line breaks as hard line breaks, which
- `ENABLE_HARD_LINE_BREAK_IN_COMMENTS`: **true**: Render soft line breaks as hard line breaks in comments, which
means a single newline character between paragraphs will cause a line break and adding
trailing whitespace to paragraphs is not necessary to force a line break.
- `ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS`: **false**: Render soft line breaks as hard line breaks in documents, which
means a single newline character between paragraphs will cause a line break and adding
trailing whitespace to paragraphs is not necessary to force a line break.
- `CUSTOM_URL_SCHEMES`: Use a comma separated list (ftp,git,svn) to indicate additional
@@ -602,8 +605,8 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false`
## i18n (`i18n`)
- `LANGS`: **en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR**: List of locales shown in language selector
- `NAMES`: **English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어**: Visible names corresponding to the locales
- `LANGS`: **en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR**: List of locales shown in language selector
- `NAMES`: **English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,日本語,español,português do Brasil,Português de Portugal,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어**: Visible names corresponding to the locales
### i18n - Datepicker Language (`i18n.datelang`)
Maps locales to the languages used by the datepicker plugin
@@ -620,6 +623,7 @@ Maps locales to the languages used by the datepicker plugin
- `ja-JP`: **ja**
- `es-ES`: **es**
- `pt-BR`: **pt-BR**
- `pt-PT`: **pt**
- `pl-PL`: **pl**
- `bg-BG`: **bg**
- `it-IT`: **it**

2
go.mod
View File

@@ -37,7 +37,7 @@ require (
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect
github.com/gliderlabs/ssh v0.2.2
github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a // indirect
github.com/go-enry/go-enry/v2 v2.3.0
github.com/go-enry/go-enry/v2 v2.5.2
github.com/go-git/go-billy/v5 v5.0.0
github.com/go-git/go-git/v5 v5.0.0
github.com/go-openapi/jsonreference v0.19.3 // indirect

12
go.sum
View File

@@ -193,10 +193,10 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a h1:FQqo
github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8=
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
github.com/go-enry/go-enry/v2 v2.3.0 h1:o8KwgY6uSplysrIpj+Y42J/xGPp90ogVpxE2Z3s8Unk=
github.com/go-enry/go-enry/v2 v2.3.0/go.mod h1:+xFJwbqWi15bvqFHb2ELUWVRKFQtwB61+sDrkvvxxGI=
github.com/go-enry/go-oniguruma v1.2.0 h1:oBO9XC1IDT9+AoWW5oFsa/7gFeOPacEqDbyXZKWXuDs=
github.com/go-enry/go-oniguruma v1.2.0/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
github.com/go-enry/go-enry/v2 v2.5.2 h1:3f3PFAO6JitWkPi1GQ5/m6Xu4gNL1U5soJ8QaYqJ0YQ=
github.com/go-enry/go-enry/v2 v2.5.2/go.mod h1:GVzIiAytiS5uT/QiuakK7TF1u4xDab87Y8V5EJRpsIQ=
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
@@ -616,8 +616,6 @@ github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDW
github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ=
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/toqueteos/trie v1.0.0 h1:8i6pXxNUXNRAqP246iibb7w/pSFquNTQ+uNfriG7vlk=
github.com/toqueteos/trie v1.0.0/go.mod h1:Ywk48QhEqhU1+DwhMkJ2x7eeGxDHiGkAdc9+0DYcbsM=
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ=
@@ -876,8 +874,6 @@ gopkg.in/testfixtures.v2 v2.5.0 h1:N08B7l2GzFQenyYbzqthDnKAA+cmb17iAZhhFxr7JHw=
gopkg.in/testfixtures.v2 v2.5.0/go.mod h1:vyAq+MYCgNpR29qitQdLZhdbLFf4mR/2MFJRFoQZZ2M=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/toqueteos/substring.v1 v1.0.2 h1:urLqCeMm6x/eTuQa1oZerNw8N1KNOIp5hD5kGL7lFsE=
gopkg.in/toqueteos/substring.v1 v1.0.2/go.mod h1:Eb2Z1UYehlVK8LYW2WBVR2rwbujsz3aX8XDrM1vbNew=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=

View File

@@ -32,7 +32,7 @@ func TestGPGKeys(t *testing.T) {
results: []int{http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized},
},
{name: "LoggedAsUser2", makeRequest: session.MakeRequest, token: token,
results: []int{http.StatusOK, http.StatusOK, http.StatusNotFound, http.StatusNoContent, http.StatusInternalServerError, http.StatusInternalServerError, http.StatusCreated, http.StatusCreated}},
results: []int{http.StatusOK, http.StatusOK, http.StatusNotFound, http.StatusNoContent, http.StatusUnprocessableEntity, http.StatusNotFound, http.StatusCreated, http.StatusCreated}},
}
for _, tc := range tt {

View File

@@ -58,7 +58,7 @@ func TestAPIMergePullWIP(t *testing.T) {
session.MakeRequest(t, req, http.StatusMethodNotAllowed)
}
func TestAPICreatePullSuccess1(t *testing.T) {
func TestAPICreatePullSuccess(t *testing.T) {
defer prepareTestEnv(t)()
repo10 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository)
// repo10 have code, pulls units.
@@ -78,7 +78,7 @@ func TestAPICreatePullSuccess1(t *testing.T) {
session.MakeRequest(t, req, 201)
}
func TestAPICreatePullSuccess2(t *testing.T) {
func TestAPIEditPull(t *testing.T) {
defer prepareTestEnv(t)()
repo10 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository)
owner10 := models.AssertExistsAndLoadBean(t, &models.User{ID: repo10.OwnerID}).(*models.User)
@@ -90,6 +90,21 @@ func TestAPICreatePullSuccess2(t *testing.T) {
Base: "master",
Title: "create a success pr",
})
pull := new(api.PullRequest)
resp := session.MakeRequest(t, req, 201)
DecodeJSON(t, resp, pull)
assert.EqualValues(t, "master", pull.Base.Name)
session.MakeRequest(t, req, 201)
req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d?token=%s", owner10.Name, repo10.Name, pull.Index, token), &api.EditPullRequestOption{
Base: "feature/1",
Title: "edit a this pr",
})
resp = session.MakeRequest(t, req, 201)
DecodeJSON(t, resp, pull)
assert.EqualValues(t, "feature/1", pull.Base.Name)
req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d?token=%s", owner10.Name, repo10.Name, pull.Index, token), &api.EditPullRequestOption{
Base: "not-exist",
})
session.MakeRequest(t, req, 404)
}

View File

@@ -189,7 +189,7 @@ func TestAPICreateFile(t *testing.T) {
treePath = "README.md"
url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
resp = session.MakeRequest(t, req, http.StatusInternalServerError)
resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity)
expectedAPIError := context.APIError{
Message: "repository file already exists [path: " + treePath + "]",
URL: setting.API.SwaggerURL,

View File

@@ -208,7 +208,7 @@ func TestAPIUpdateFile(t *testing.T) {
updateFileOptions.SHA = "badsha"
url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
resp = session.MakeRequest(t, req, http.StatusInternalServerError)
resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity)
expectedAPIError := context.APIError{
Message: "sha does not match [given: " + updateFileOptions.SHA + ", expected: " + correctSHA + "]",
URL: setting.API.SwaggerURL,

View File

@@ -76,6 +76,53 @@ nARUPZ9SqaUmRm+KGsSyoYnvN9apiDk5KVQoyfrmweNN7DCIIcoh/B9Ax8nmouKz
yBB2fjCM/bJNtN/AsgYbZIScuYK/xqTkwNtbe5WdCyD/QJOHTsPJzx59hgSVo6gf
Fe8VBnxHtrY8gPSUU3gkhYLvLzyVX+YLNzRcffobd8gJbfumwFJUkz91oGvYz7xg
XN2qmsgBNCbTIzWZMpRDMAbY+n2QFImGf+EJZlMdj6gOrIYq8N4+nMW1FwJivsOb
muqySyjZnD2AYjEA6OYPXfCVhaB5fTfhQXbIrZbgsEh4ob/eIdM=
=oSDR
muqySyjZnD2AYjEA6OYPXfCVhaB5fTfhQXbIrZbgsEh4ob/eIdOdBVgEXta5egEM
AMYlmZ47NqBMBeaN0o/ahYMe8eIMaroWkufMfC9VRBSMAkpbDl34oNp0cflmnMYo
AFAl8ucRMFTiUnjiWpo27q14tjSyDVsn/CqwbnrgJgCFNV/MGsYsToEkb4JwDIRC
bky+1BvqvI8RMlO3MlwzrlIaMrlQfx5NtUb9TyO7S4xZTz864+Ty5p3HhRwbdZMe
Ko8sfXFhCcCHFXosI0mX83EyzsrXlbkGRawId7jvrdOAUg/cYP8f/XmV6z1NHHH9
cvz+3oLOGuVxUdG0KuS/jigHrLWdRuKM3xfEeesp870yZU3AbyFdoHnGXROJePTl
FV8j2P5Ahf/yuVhjdyJSKdZC2h6+HtLG9RiGgLviLLYhtlZG2H6pYyKY5Ud3php+
qw1aYL1xtdxrHYkQlAa0vLY/mwpuPfMke9I+rtnrwlLRMCstdiN34ybZ4sRD+gL1
w5VIZ/aM6/Gsczd3s/T8psIi09TKPfEU2gWLMGvlDsgz+aSDdVP7XYQpNglaEPet
PwARAQABAAv8CHg6+hnV2pblTwGTlTU7V8DO3gwMfn/QhQ/8ju66G5a7J6p/ZreQ
nfCJnqYq4AgoW0SuqVSBbbTENF6YjixNmiSlb9iHMZ+ilms24xG0Y3lOMBYYCY3Y
nTSNf6nXyconz31TW7jLmTdG9hpykKEKO9WFgt5UpgWe+2CAgtUoBDZyaLrVBZ2h
te99WmziDbPQZeZPm7UQ0aX0iRBclxy4+dxjcnrcmi1mdQAM/glgs2sHbEjN7JnV
dTOvUSN7/8ixj6I719Wx6MN6jE+BNd0ytZOun6tcDl0vamfT5fBpqbQoJMib2ggo
+FGg9VFnzEMLqyI47LfOKUjCIhwVsxS4q9HXa2FtpO8UfRMPjDKgDZQzRTRJScrP
s1NJ9HiM/eCHS1YjRmgroo60HygxkoLVCHp+Rz/hi0tG/ptv4q6mdnm8Mwb5JJtV
48EvmZoNTWl9xOez1wmQn6caVHipc0qDqn/veoe8N5wdc+3hoMEXbSXqU+kx2KUa
cVxCCVoUeURhBgDUGWtx34j1y17zE92BYhtVJTCU89dDe4wOEqGPyCGvRtgTmZ+1
KwWr66pij91MV9mlY+7Ue2QHUSmgav2EFGIjVes956p4/F/CJ6qaYoekirMSnmX5
jhRt4p6RW7m4omha3LAQ+gN4Fqa4acZUywENBvv1x3v+IWbjGJGn3eBnRrP3o9P+
QUAtyMifiRm0ZN8J767o+bzUVmscXrkh7Qml47lQfDToyRI1UZZQmP2izpwHcwbZ
NtfkgRUdeEq4GJUGAO8o4Oebbt0ALZ54E2LHhk8xi4ofKkFBDCkUFjcqS3bJJNck
rkhfqEkMLETNhPbiC4TRNiunI5PXOinwNPkKI8P/hfp4S49WdIvnARazCoxjZNtl
0Cbo+F1wtOH9FZaaWzNlU2lCQ2JJ3MCpLHz+nEmdYWOIWGQu2/s7smLODVEFbYKR
50VWVRL7mB83v1XdfMFvExdQ7i5MOX4hFvmwi/WJIKClJfhNwTrHp6Jrm9jA66RL
+dNyPKfwcFcYrqt1gwYAruZzP7QgTYVL+cmvGtCaHY4KoR8hanbpqR4YbzzyEXwS
ll2FUCaVSokuRAdH3+/CHF9bqog3Zvn6HYcCS/A/rHVGIU9a+7s5IbRe0Ysc2FAN
Nm9AsC5YnuyoAjW3cJGaZLYxp2WOZcMEXZeLPFYrNz22R1nRoxnUIPRpsKICXcK0
aC4rSMk479jc/8WprWx4d45EVG+6Gsh1AT8LVhDL9yHFrh50ss2jCe1Fnftet6DI
V5zHcxBx4sCs91aPxxe12UiJA2wEGAEKACAWIQQ4G/p4KVUOUEVu5g5R68KXFICq
DwUCXta5egIbAgHACRBR68KXFICqD8D0IAQZAQoAHRYhBKAm5ShdO9gmF/o8jan0
RkmWoKbKBQJe1rl6AAoJEKn0RkmWoKbKacUL/3YYKmiVvcr5LYFzMdwdahkla+6m
hEEkL0l3dJNuU97Ou71tA1ieF0fjbVRSWjXKsntKwhyPoXjaZEZwMmv7iZ8BXV+b
oO/EG5sg2/6iukJFXZqGnQwMdLVo1jPoXDteZU1qYiCoxLHhGhHL7ivtD1ygEi6w
/cMbbOEB5Le1vOWIwqazs8dDcAYyy1PKthRl0ygvh8CpqPwy+AK3uLm0TVwetQAp
taux0bDYWCb5Aft1r1nlV44gU4RiC131TDo+TKd754+UuI+UHk1D+LjTmZxRX2S6
fXgoMXzrWmthGPdqvVOgKWm7Ef18hmaBECvPnp/tUJeDVVe02KrYQi8Bf2kxveSd
8T0N/ExcydU9HgzTL8MuyPI+yp086elQzKJu6vb9tpgxCcglQZrUNT9Uy82pzTRY
z9MmhnCDI2SD5L/CW5PsNpPTPy7s3f9DOV0G5Vka4LTSBOCK64NvAGBmRf8rFjJU
lPtRPhC7h6uHdUIx3Q550Xogvq5sQm8UBCsbG8OJDADT3FJSIulR9Sh96OsES3sc
H09juN4KcbpS03MAeUFwXqw3jBMhDoGKlsjX17Jf31qh/nI/XjigS3XWyj1BLSMG
rJfH0NyYoGDCnff37tf+8lD9km9TlnV4Qjd9ujYbDRsefhaSjLVcy/gqdxZEuNBC
BWmGwsmLI3nyZ4KDtNsa5JUHUNNZLBN20hvmE41Eszmz4Yg9Ho9DxKiFKvzUULMc
bnMHaVHseHHq6+NVUnN1SAcOA0ygjnEid8D57RtdBCD90LXjLB7vlR+HaSMZYOnr
DtseivHvqqy4+rxhwV2S3avnls9vRwE4bV6GCiqhoBnWIZRrARLZc2OTBIya82vS
BIS1eyhjif1mE7Lqhs6aPD+eqQK2mBtQ/sidN8P/IfKfVF5siXfFbuGZLz5nRIho
Yp1z7oO3OZ09lpUk0G1h+ouIFF6goDP48M/AKtbvs9OWk3QKxnOUZD8sRncq95x6
m4q1MVb+aJyxwBqDRGaFY+3TVArB1b+kG1JsAvV5dag=
=511T
-----END PGP PRIVATE KEY BLOCK-----

View File

@@ -194,7 +194,7 @@ func TestCantMergeWorkInProgress(t *testing.T) {
req := NewRequest(t, "GET", resp.Header().Get("Location"))
resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
text := strings.TrimSpace(htmlDoc.doc.Find(".attached.header > .text.grey").Last().Text())
text := strings.TrimSpace(htmlDoc.doc.Find(".attached.merge-section.no-header > .text.grey").Last().Text())
assert.NotEmpty(t, text, "Can't find WIP text")
// remove <strong /> from lang

View File

@@ -10,6 +10,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"xorm.io/builder"
)
// consistencyCheckable a type that can be tested for database consistency
@@ -167,3 +168,118 @@ func (action *Action) checkForConsistency(t *testing.T) {
repo := AssertExistsAndLoadBean(t, &Repository{ID: action.RepoID}).(*Repository)
assert.Equal(t, repo.IsPrivate, action.IsPrivate, "action: %+v", action)
}
// CountOrphanedLabels return count of labels witch are broken and not accessible via ui anymore
func CountOrphanedLabels() (int64, error) {
noref, err := x.Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count("label.id")
if err != nil {
return 0, err
}
norepo, err := x.Table("label").
Join("LEFT", "repository", "label.repo_id=repository.id").
Where(builder.IsNull{"repository.id"}).And(builder.Gt{"label.repo_id": 0}).
Count("id")
if err != nil {
return 0, err
}
noorg, err := x.Table("label").
Join("LEFT", "`user`", "label.org_id=`user`.id").
Where(builder.IsNull{"`user`.id"}).And(builder.Gt{"label.org_id": 0}).
Count("id")
if err != nil {
return 0, err
}
return noref + norepo + noorg, nil
}
// DeleteOrphanedLabels delete labels witch are broken and not accessible via ui anymore
func DeleteOrphanedLabels() error {
// delete labels with no reference
if _, err := x.Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil {
return err
}
// delete labels with none existing repos
if _, err := x.In("id", builder.Select("label.id").From("label").
Join("LEFT", "repository", "label.repo_id=repository.id").
Where(builder.IsNull{"repository.id"}).And(builder.Gt{"label.repo_id": 0})).
Delete(Label{}); err != nil {
return err
}
// delete labels with none existing orgs
if _, err := x.In("id", builder.Select("label.id").From("label").
Join("LEFT", "`user`", "label.org_id=`user`.id").
Where(builder.IsNull{"`user`.id"}).And(builder.Gt{"label.org_id": 0})).
Delete(Label{}); err != nil {
return err
}
return nil
}
// CountOrphanedIssues count issues without a repo
func CountOrphanedIssues() (int64, error) {
return x.Table("issue").
Join("LEFT", "repository", "issue.repo_id=repository.id").
Where(builder.IsNull{"repository.id"}).
Count("id")
}
// DeleteOrphanedIssues delete issues without a repo
func DeleteOrphanedIssues() error {
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}
var ids []int64
if err := sess.Table("issue").Distinct("issue.repo_id").
Join("LEFT", "repository", "issue.repo_id=repository.id").
Where(builder.IsNull{"repository.id"}).GroupBy("issue.repo_id").
Find(&ids); err != nil {
return err
}
var attachmentPaths []string
for i := range ids {
paths, err := deleteIssuesByRepoID(sess, ids[i])
if err != nil {
return err
}
attachmentPaths = append(attachmentPaths, paths...)
}
if err := sess.Commit(); err != nil {
return err
}
// Remove issue attachment files.
for i := range attachmentPaths {
removeAllWithNotice(x, "Delete issue attachment", attachmentPaths[i])
}
return nil
}
// CountOrphanedObjects count subjects with have no existing refobject anymore
func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) {
return x.Table("`"+subject+"`").
Join("LEFT", refobject, joinCond).
Where(builder.IsNull{"`" + refobject + "`.id"}).
Count("id")
}
// DeleteOrphanedObjects delete subjects with have no existing refobject anymore
func DeleteOrphanedObjects(subject, refobject, joinCond string) error {
_, err := x.In("id", builder.Select("`"+subject+"`.id").
From("`"+subject+"`").
Join("LEFT", "`"+refobject+"`", joinCond).
Where(builder.IsNull{"`" + refobject + "`.id"})).
Delete("`" + subject + "`")
return err
}

View File

@@ -273,7 +273,7 @@ func parseGPGKey(ownerID int64, e *openpgp.Entity) (*GPGKey, error) {
for i, k := range e.Subkeys {
subs, err := parseSubGPGKey(ownerID, pubkey.KeyIdString(), k.PublicKey, expiry)
if err != nil {
return nil, err
return nil, ErrGPGKeyParsing{ParseError: err}
}
subkeys[i] = subs
}
@@ -741,6 +741,21 @@ func verifyWithGPGSettings(gpgSettings *git.GPGSettings, sig *packet.Signature,
CanSign: pubkey.CanSign(),
KeyID: pubkey.KeyIdString(),
}
for _, subKey := range ekey.Subkeys {
content, err := base64EncPubKey(subKey.PublicKey)
if err != nil {
return &CommitVerification{
CommittingUser: committer,
Verified: false,
Reason: "gpg.error.generate_hash",
}
}
k.SubsKey = append(k.SubsKey, &GPGKey{
Content: content,
CanSign: subKey.PublicKey.CanSign(),
KeyID: subKey.PublicKey.KeyIdString(),
})
}
if commitVerification := hashAndVerifyWithSubKeys(sig, payload, k, committer, &User{
Name: gpgSettings.Name,
Email: gpgSettings.Email,

View File

@@ -76,7 +76,6 @@ var (
const issueTasksRegexpStr = `(^\s*[-*]\s\[[\sxX]\]\s.)|(\n\s*[-*]\s\[[\sxX]\]\s.)`
const issueTasksDoneRegexpStr = `(^\s*[-*]\s\[[xX]\]\s.)|(\n\s*[-*]\s\[[xX]\]\s.)`
const issueMaxDupIndexAttempts = 3
const maxIssueIDs = 950
func init() {
issueTasksPat = regexp.MustCompile(issueTasksRegexpStr)
@@ -249,7 +248,7 @@ func (issue *Issue) loadReactions(e Engine) (err error) {
}
func (issue *Issue) loadMilestone(e Engine) (err error) {
if issue.Milestone == nil && issue.MilestoneID > 0 {
if (issue.Milestone == nil || issue.Milestone.ID != issue.MilestoneID) && issue.MilestoneID > 0 {
issue.Milestone, err = getMilestoneByRepoID(e, issue.RepoID, issue.MilestoneID)
if err != nil && !IsErrMilestoneNotExist(err) {
return fmt.Errorf("getMilestoneByRepoID [repo_id: %d, milestone_id: %d]: %v", issue.RepoID, issue.MilestoneID, err)
@@ -1114,9 +1113,6 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
}
if len(opts.IssueIDs) > 0 {
if len(opts.IssueIDs) > maxIssueIDs {
opts.IssueIDs = opts.IssueIDs[:maxIssueIDs]
}
sess.In("issue.id", opts.IssueIDs)
}
@@ -1360,9 +1356,6 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats,
Where("issue.repo_id = ?", opts.RepoID)
if len(opts.IssueIDs) > 0 {
if len(opts.IssueIDs) > maxIssueIDs {
opts.IssueIDs = opts.IssueIDs[:maxIssueIDs]
}
sess.In("issue.id", opts.IssueIDs)
}
@@ -1446,9 +1439,6 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
cond = cond.And(builder.In("issue.repo_id", opts.RepoIDs))
}
if len(opts.IssueIDs) > 0 {
if len(opts.IssueIDs) > maxIssueIDs {
opts.IssueIDs = opts.IssueIDs[:maxIssueIDs]
}
cond = cond.And(builder.In("issue.id", opts.IssueIDs))
}
@@ -1916,3 +1906,70 @@ func UpdateReactionsMigrationsByType(gitServiceType structs.GitServiceType, orig
})
return err
}
func deleteIssuesByRepoID(sess Engine, repoID int64) (attachmentPaths []string, err error) {
deleteCond := builder.Select("id").From("issue").Where(builder.Eq{"issue.repo_id": repoID})
// Delete comments and attachments
if _, err = sess.In("issue_id", deleteCond).
Delete(&Comment{}); err != nil {
return
}
// Dependencies for issues in this repository
if _, err = sess.In("issue_id", deleteCond).
Delete(&IssueDependency{}); err != nil {
return
}
// Delete dependencies for issues in other repositories
if _, err = sess.In("dependency_id", deleteCond).
Delete(&IssueDependency{}); err != nil {
return
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&IssueUser{}); err != nil {
return
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&Reaction{}); err != nil {
return
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&IssueWatch{}); err != nil {
return
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&Stopwatch{}); err != nil {
return
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&TrackedTime{}); err != nil {
return
}
var attachments []*Attachment
if err = sess.In("issue_id", deleteCond).
Find(&attachments); err != nil {
return
}
for j := range attachments {
attachmentPaths = append(attachmentPaths, attachments[j].LocalPath())
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&Attachment{}); err != nil {
return
}
if _, err = sess.Delete(&Issue{RepoID: repoID}); err != nil {
return
}
return
}

View File

@@ -212,6 +212,8 @@ var migrations = []Migration{
NewMigration("Add ResolveDoerID to Comment table", addResolveDoerIDCommentColumn),
// v139 -> v140
NewMigration("prepend refs/heads/ to issue refs", prependRefsHeadsToIssueRefs),
// v140 -> v141
NewMigration("Save detected language file size to database instead of percent", fixLanguageStatsToSaveSize),
}
// GetCurrentDBVersion returns the current db version

View File

@@ -8,8 +8,10 @@ import (
"crypto/md5"
"fmt"
"io/ioutil"
"math"
"os"
"path/filepath"
"time"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -26,8 +28,19 @@ func renameExistingUserAvatarName(x *xorm.Engine) error {
LowerName string `xorm:"UNIQUE NOT NULL"`
Avatar string
}
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
count, err := x.Count(new(User))
if err != nil {
return err
}
log.Info("%d User Avatar(s) to migrate ...", count)
deleteList := make(map[string]struct{})
start := 0
migrated := 0
for {
if err := sess.Begin(); err != nil {
return fmt.Errorf("session.Begin: %v", err)
@@ -73,6 +86,19 @@ func renameExistingUserAvatarName(x *xorm.Engine) error {
}
deleteList[filepath.Join(setting.AvatarUploadPath, oldAvatar)] = struct{}{}
migrated++
select {
case <-ticker.C:
log.Info(
"%d/%d (%2.0f%%) User Avatar(s) migrated (%d old avatars to be deleted) in %d batches. %d Remaining ...",
migrated,
count,
float64(migrated)/float64(count)*100,
len(deleteList),
int(math.Ceil(float64(migrated)/float64(50))),
count-int64(migrated))
default:
}
}
if err := sess.Commit(); err != nil {
_ = sess.Rollback()
@@ -80,11 +106,28 @@ func renameExistingUserAvatarName(x *xorm.Engine) error {
}
}
deleteCount := len(deleteList)
log.Info("Deleting %d old avatars ...", deleteCount)
i := 0
for file := range deleteList {
if err := os.Remove(file); err != nil {
log.Warn("os.Remove: %v", err)
}
i++
select {
case <-ticker.C:
log.Info(
"%d/%d (%2.0f%%) Old User Avatar(s) deleted. %d Remaining ...",
i,
deleteCount,
float64(i)/float64(deleteCount)*100,
deleteCount-i)
default:
}
}
log.Info("Completed migrating %d User Avatar(s) and deleting %d Old Avatars", count, deleteCount)
return nil
}

View File

@@ -6,8 +6,10 @@ package migrations
import (
"fmt"
"math"
"path/filepath"
"strings"
"time"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
@@ -43,17 +45,27 @@ func fixMergeBase(x *xorm.Engine) error {
limit = 50
}
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
count, err := x.Count(new(PullRequest))
if err != nil {
return err
}
log.Info("%d Pull Request(s) to migrate ...", count)
i := 0
start := 0
for {
prs := make([]PullRequest, 0, 50)
if err := x.Limit(limit, i).Asc("id").Find(&prs); err != nil {
if err := x.Limit(limit, start).Asc("id").Find(&prs); err != nil {
return fmt.Errorf("Find: %v", err)
}
if len(prs) == 0 {
break
}
i += len(prs)
start += 50
for _, pr := range prs {
baseRepo := &Repository{ID: pr.BaseRepoID}
has, err := x.Table("repository").Get(baseRepo)
@@ -102,8 +114,14 @@ func fixMergeBase(x *xorm.Engine) error {
}
pr.MergeBase = strings.TrimSpace(pr.MergeBase)
x.ID(pr.ID).Cols("merge_base").Update(pr)
i++
select {
case <-ticker.C:
log.Info("%d/%d (%2.0f%%) Pull Request(s) migrated in %d batches. %d PRs Remaining ...", i, count, float64(i)/float64(count)*100, int(math.Ceil(float64(i)/float64(limit))), count-int64(i))
default:
}
}
}
log.Info("Completed migrating %d Pull Request(s) in: %d batches", count, int(math.Ceil(float64(i)/float64(limit))))
return nil
}

View File

@@ -6,8 +6,10 @@ package migrations
import (
"fmt"
"math"
"path/filepath"
"strings"
"time"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
@@ -43,17 +45,26 @@ func refixMergeBase(x *xorm.Engine) error {
limit = 50
}
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
count, err := x.Where("has_merged = ?", true).Count(new(PullRequest))
if err != nil {
return err
}
log.Info("%d Merged Pull Request(s) to migrate ...", count)
i := 0
start := 0
for {
prs := make([]PullRequest, 0, 50)
if err := x.Limit(limit, i).Asc("id").Where("has_merged = ?", true).Find(&prs); err != nil {
if err := x.Limit(limit, start).Asc("id").Where("has_merged = ?", true).Find(&prs); err != nil {
return fmt.Errorf("Find: %v", err)
}
if len(prs) == 0 {
break
}
i += len(prs)
start += 50
for _, pr := range prs {
baseRepo := &Repository{ID: pr.BaseRepoID}
has, err := x.Table("repository").Get(baseRepo)
@@ -90,7 +101,15 @@ func refixMergeBase(x *xorm.Engine) error {
}
pr.MergeBase = strings.TrimSpace(pr.MergeBase)
x.ID(pr.ID).Cols("merge_base").Update(pr)
i++
select {
case <-ticker.C:
log.Info("%d/%d (%2.0f%%) Pull Request(s) migrated in %d batches. %d PRs Remaining ...", i, count, float64(i)/float64(count)*100, int(math.Ceil(float64(i)/float64(limit))), count-int64(i))
default:
}
}
}
log.Info("Completed migrating %d Pull Request(s) in: %d batches", count, int(math.Ceil(float64(i)/float64(limit))))
return nil
}

View File

@@ -6,25 +6,60 @@ package migrations
import (
"fmt"
"math"
"path/filepath"
"strings"
"time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
pull_service "code.gitea.io/gitea/services/pull"
"xorm.io/xorm"
)
func addCommitDivergenceToPulls(x *xorm.Engine) error {
type Repository struct {
ID int64 `xorm:"pk autoincr"`
OwnerID int64 `xorm:"UNIQUE(s) index"`
OwnerName string
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
Name string `xorm:"INDEX NOT NULL"`
}
type PullRequest struct {
ID int64 `xorm:"pk autoincr"`
CommitsAhead int
CommitsBehind int
BaseRepoID int64 `xorm:"INDEX"`
BaseBranch string
HasMerged bool `xorm:"INDEX"`
MergedCommitID string `xorm:"VARCHAR(40)"`
}
if err := x.Sync2(new(models.PullRequest)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}
var last int
last := 0
migrated := 0
batchSize := setting.Database.IterateBufferSize
sess := x.NewSession()
defer sess.Close()
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
count, err := sess.Where("has_merged = ?", false).Count(new(PullRequest))
if err != nil {
return err
}
log.Info("%d Unmerged Pull Request(s) to migrate ...", count)
for {
if err := sess.Begin(); err != nil {
return err
@@ -37,27 +72,53 @@ func addCommitDivergenceToPulls(x *xorm.Engine) error {
if len(results) == 0 {
break
}
last += len(results)
last += batchSize
for _, pr := range results {
divergence, err := pull_service.GetDiverging(pr)
baseRepo := &Repository{ID: pr.BaseRepoID}
has, err := x.Table("repository").Get(baseRepo)
if err != nil {
return fmt.Errorf("Unable to get base repo %d %v", pr.BaseRepoID, err)
}
if !has {
log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID)
continue
}
userPath := filepath.Join(setting.RepoRootPath, strings.ToLower(baseRepo.OwnerName))
repoPath := filepath.Join(userPath, strings.ToLower(baseRepo.Name)+".git")
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
divergence, err := git.GetDivergingCommits(repoPath, pr.BaseBranch, gitRefName)
if err != nil {
log.Warn("Could not recalculate Divergence for pull: %d", pr.ID)
pr.CommitsAhead = 0
pr.CommitsBehind = 0
}
if divergence != nil {
pr.CommitsAhead = divergence.Ahead
pr.CommitsBehind = divergence.Behind
}
pr.CommitsAhead = divergence.Ahead
pr.CommitsBehind = divergence.Behind
if _, err = sess.ID(pr.ID).Cols("commits_ahead", "commits_behind").Update(pr); err != nil {
return fmt.Errorf("Update Cols: %v", err)
}
migrated++
}
if err := sess.Commit(); err != nil {
return err
}
select {
case <-ticker.C:
log.Info(
"%d/%d (%2.0f%%) Pull Request(s) migrated in %d batches. %d PRs Remaining ...",
migrated,
count,
float64(migrated)/float64(count)*100,
int(math.Ceil(float64(migrated)/float64(batchSize))),
count-int64(migrated))
default:
}
}
log.Info("Completed migrating %d Pull Request(s) in: %d batches", count, int(math.Ceil(float64(migrated)/float64(batchSize))))
return nil
}

56
models/migrations/v140.go Normal file
View File

@@ -0,0 +1,56 @@
// Copyright 2020 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 migrations
import (
"fmt"
"code.gitea.io/gitea/modules/setting"
"xorm.io/xorm"
)
func fixLanguageStatsToSaveSize(x *xorm.Engine) error {
// LanguageStat see models/repo_language_stats.go
type LanguageStat struct {
Size int64 `xorm:"NOT NULL DEFAULT 0"`
}
// RepoIndexerType specifies the repository indexer type
type RepoIndexerType int
const (
// RepoIndexerTypeCode code indexer
RepoIndexerTypeCode RepoIndexerType = iota // 0
// RepoIndexerTypeStats repository stats indexer
RepoIndexerTypeStats // 1
)
// RepoIndexerStatus see models/repo_indexer.go
type RepoIndexerStatus struct {
IndexerType RepoIndexerType `xorm:"INDEX(s) NOT NULL DEFAULT 0"`
}
if err := x.Sync2(new(LanguageStat)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}
x.Delete(&RepoIndexerStatus{IndexerType: RepoIndexerTypeStats})
// Delete language stat statuses
truncExpr := "TRUNCATE TABLE"
if setting.Database.UseSQLite3 {
truncExpr = "DELETE FROM"
}
// Delete language stats
if _, err := x.Exec(fmt.Sprintf("%s language_stat", truncExpr)); err != nil {
return err
}
sess := x.NewSession()
defer sess.Close()
return dropTableColumns(sess, "language_stat", "percentage")
}

View File

@@ -182,6 +182,10 @@ func SetEngine() (err error) {
}
// NewEngine initializes a new xorm.Engine
// This function must never call .Sync2() if the provided migration function fails.
// When called from the "doctor" command, the migration function is a version check
// that prevents the doctor from fixing anything in the database if the migration level
// is different from the expected value.
func NewEngine(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err error) {
if err = SetEngine(); err != nil {
return err

View File

@@ -35,7 +35,6 @@ import (
"code.gitea.io/gitea/modules/util"
"github.com/unknwon/com"
"xorm.io/builder"
)
var (
@@ -174,9 +173,10 @@ type Repository struct {
*Mirror `xorm:"-"`
Status RepositoryStatus `xorm:"NOT NULL DEFAULT 0"`
RenderingMetas map[string]string `xorm:"-"`
Units []*RepoUnit `xorm:"-"`
PrimaryLanguage *LanguageStat `xorm:"-"`
RenderingMetas map[string]string `xorm:"-"`
DocumentRenderingMetas map[string]string `xorm:"-"`
Units []*RepoUnit `xorm:"-"`
PrimaryLanguage *LanguageStat `xorm:"-"`
IsFork bool `xorm:"INDEX NOT NULL DEFAULT false"`
ForkID int64 `xorm:"INDEX"`
@@ -534,11 +534,12 @@ func (repo *Repository) mustOwner(e Engine) *User {
// ComposeMetas composes a map of metas for properly rendering issue links and external issue trackers.
func (repo *Repository) ComposeMetas() map[string]string {
if repo.RenderingMetas == nil {
if len(repo.RenderingMetas) == 0 {
metas := map[string]string{
"user": repo.OwnerName,
"repo": repo.Name,
"repoPath": repo.RepoPath(),
"mode": "comment",
}
unit, err := repo.GetUnit(UnitTypeExternalTracker)
@@ -570,6 +571,19 @@ func (repo *Repository) ComposeMetas() map[string]string {
return repo.RenderingMetas
}
// ComposeDocumentMetas composes a map of metas for properly rendering documents
func (repo *Repository) ComposeDocumentMetas() map[string]string {
if len(repo.DocumentRenderingMetas) == 0 {
metas := map[string]string{}
for k, v := range repo.ComposeMetas() {
metas[k] = v
}
metas["mode"] = "document"
repo.DocumentRenderingMetas = metas
}
return repo.DocumentRenderingMetas
}
// DeleteWiki removes the actual and local copy of repository wiki.
func (repo *Repository) DeleteWiki() error {
return repo.deleteWiki(x)
@@ -1575,67 +1589,9 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
return fmt.Errorf("deleteBeans: %v", err)
}
deleteCond := builder.Select("id").From("issue").Where(builder.Eq{"repo_id": repoID})
// Delete comments and attachments
if _, err = sess.In("issue_id", deleteCond).
Delete(&Comment{}); err != nil {
return err
}
// Dependencies for issues in this repository
if _, err = sess.In("issue_id", deleteCond).
Delete(&IssueDependency{}); err != nil {
return err
}
// Delete dependencies for issues in other repositories
if _, err = sess.In("dependency_id", deleteCond).
Delete(&IssueDependency{}); err != nil {
return err
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&IssueUser{}); err != nil {
return err
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&Reaction{}); err != nil {
return err
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&IssueWatch{}); err != nil {
return err
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&Stopwatch{}); err != nil {
return err
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&TrackedTime{}); err != nil {
return err
}
attachments = attachments[:0]
if err = sess.Join("INNER", "issue", "issue.id = attachment.issue_id").
Where("issue.repo_id = ?", repoID).
Find(&attachments); err != nil {
return err
}
attachmentPaths := make([]string, 0, len(attachments))
for j := range attachments {
attachmentPaths = append(attachmentPaths, attachments[j].LocalPath())
}
if _, err = sess.In("issue_id", deleteCond).
Delete(&Attachment{}); err != nil {
return err
}
if _, err = sess.Delete(&Issue{RepoID: repoID}); err != nil {
// Delete Issues and related objects
var attachmentPaths []string
if attachmentPaths, err = deleteIssuesByRepoID(sess, repoID); err != nil {
return err
}

View File

@@ -20,7 +20,8 @@ type LanguageStat struct {
CommitID string
IsPrimary bool
Language string `xorm:"VARCHAR(30) UNIQUE(s) INDEX NOT NULL"`
Percentage float32 `xorm:"NUMERIC(5,2) NOT NULL DEFAULT 0"`
Percentage float32 `xorm:"-"`
Size int64 `xorm:"NOT NULL DEFAULT 0"`
Color string `xorm:"-"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
}
@@ -34,12 +35,36 @@ func (stats LanguageStatList) loadAttributes() {
}
}
func (stats LanguageStatList) getLanguagePercentages() map[string]float32 {
langPerc := make(map[string]float32)
var otherPerc float32 = 100
var total int64
for _, stat := range stats {
total += stat.Size
}
if total > 0 {
for _, stat := range stats {
perc := float32(math.Round(float64(stat.Size)/float64(total)*1000) / 10)
if perc <= 0.1 {
continue
}
otherPerc -= perc
langPerc[stat.Language] = perc
}
otherPerc = float32(math.Round(float64(otherPerc)*10) / 10)
}
if otherPerc > 0 {
langPerc["other"] = otherPerc
}
return langPerc
}
func (repo *Repository) getLanguageStats(e Engine) (LanguageStatList, error) {
stats := make(LanguageStatList, 0, 6)
if err := e.Where("`repo_id` = ?", repo.ID).Desc("`percentage`").Find(&stats); err != nil {
if err := e.Where("`repo_id` = ?", repo.ID).Desc("`size`").Find(&stats); err != nil {
return nil, err
}
stats.loadAttributes()
return stats, nil
}
@@ -54,13 +79,18 @@ func (repo *Repository) GetTopLanguageStats(limit int) (LanguageStatList, error)
if err != nil {
return nil, err
}
perc := stats.getLanguagePercentages()
topstats := make(LanguageStatList, 0, limit)
var other float32
for i := range stats {
if stats[i].Language == "other" || len(topstats) >= limit {
other += stats[i].Percentage
if _, ok := perc[stats[i].Language]; !ok {
continue
}
if stats[i].Language == "other" || len(topstats) >= limit {
other += perc[stats[i].Language]
continue
}
stats[i].Percentage = perc[stats[i].Language]
topstats = append(topstats, stats[i])
}
if other > 0 {
@@ -71,11 +101,12 @@ func (repo *Repository) GetTopLanguageStats(limit int) (LanguageStatList, error)
Percentage: float32(math.Round(float64(other)*10) / 10),
})
}
topstats.loadAttributes()
return topstats, nil
}
// UpdateLanguageStats updates the language statistics for repository
func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]float32) error {
func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]int64) error {
sess := x.NewSession()
if err := sess.Begin(); err != nil {
return err
@@ -87,15 +118,15 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
return err
}
var topLang string
var p float32
for lang, perc := range stats {
if perc > p {
p = perc
var s int64
for lang, size := range stats {
if size > s {
s = size
topLang = strings.ToLower(lang)
}
}
for lang, perc := range stats {
for lang, size := range stats {
upd := false
llang := strings.ToLower(lang)
for _, s := range oldstats {
@@ -103,8 +134,8 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
if strings.ToLower(s.Language) == llang {
s.CommitID = commitID
s.IsPrimary = llang == topLang
s.Percentage = perc
if _, err := sess.ID(s.ID).Cols("`commit_id`", "`percentage`", "`is_primary`").Update(s); err != nil {
s.Size = size
if _, err := sess.ID(s.ID).Cols("`commit_id`", "`size`", "`is_primary`").Update(s); err != nil {
return err
}
upd = true
@@ -114,11 +145,11 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
// Insert new language
if !upd {
if _, err := sess.Insert(&LanguageStat{
RepoID: repo.ID,
CommitID: commitID,
IsPrimary: llang == topLang,
Language: lang,
Percentage: perc,
RepoID: repo.ID,
CommitID: commitID,
IsPrimary: llang == topLang,
Language: lang,
Size: size,
}); err != nil {
return err
}
@@ -153,7 +184,7 @@ func CopyLanguageStat(originalRepo, destRepo *Repository) error {
return err
}
RepoLang := make(LanguageStatList, 0, 6)
if err := sess.Where("`repo_id` = ?", originalRepo.ID).Desc("`percentage`").Find(&RepoLang); err != nil {
if err := sess.Where("`repo_id` = ?", originalRepo.ID).Desc("`size`").Find(&RepoLang); err != nil {
return err
}
if len(RepoLang) > 0 {

View File

@@ -140,10 +140,13 @@ type SearchRepoOptions struct {
PriorityOwnerID int64
OrderBy SearchOrderBy
Private bool // Include private repositories in results
OnlyPrivate bool // Include only private repositories in results
StarredByID int64
AllPublic bool // Include also all public repositories of users and public organisations
AllLimited bool // Include also all public repositories of limited organisations
// None -> include public and private
// True -> include just private
// False -> incude just public
IsPrivate util.OptionalBool
// None -> include collaborative AND non-collaborative
// True -> include just collaborative
// False -> incude just non-collaborative
@@ -221,15 +224,8 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
))))
}
if opts.OnlyPrivate {
cond = cond.And(
builder.Or(
builder.Eq{"is_private": true},
builder.In("owner_id", builder.Select("id").From("`user`").Where(
builder.And(
builder.Eq{"type": UserTypeOrganization},
builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}),
)))))
if opts.IsPrivate != util.OptionalBoolNone {
cond = cond.And(builder.Eq{"is_private": opts.IsPrivate.IsTrue()})
}
if opts.Template != util.OptionalBoolNone {
@@ -249,14 +245,35 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
}
if opts.Collaborate != util.OptionalBoolFalse {
// A Collaboration is:
collaborateCond := builder.And(
// 1. Repository we don't own
builder.Neq{"owner_id": opts.OwnerID},
// 2. But we can see because of:
builder.Or(
builder.Expr("repository.id IN (SELECT repo_id FROM `access` WHERE access.user_id = ?)", opts.OwnerID),
builder.In("id", builder.Select("`team_repo`.repo_id").
// A. We have access
builder.In("`repository`.id",
builder.Select("`access`.repo_id").
From("access").
Where(builder.Eq{"`access`.user_id": opts.OwnerID})),
// B. We are in a team for
builder.In("`repository`.id", builder.Select("`team_repo`.repo_id").
From("team_repo").
Where(builder.Eq{"`team_user`.uid": opts.OwnerID}).
Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id"))),
builder.Neq{"owner_id": opts.OwnerID})
Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id")),
// C. Public repositories in private organizations that we are member of
builder.And(
builder.Eq{"`repository`.is_private": false},
builder.In("`repository`.owner_id",
builder.Select("`org_user`.org_id").
From("org_user").
Join("INNER", "`user`", "`user`.id = `org_user`.org_id").
Where(builder.Eq{
"`org_user`.uid": opts.OwnerID,
"`user`.type": UserTypeOrganization,
"`user`.visibility": structs.VisibleTypePrivate,
})))),
)
if !opts.Private {
collaborateCond = collaborateCond.And(builder.Expr("owner_id NOT IN (SELECT org_id FROM org_user WHERE org_user.uid = ? AND org_user.is_public = ?)", opts.OwnerID, false))
}

View File

@@ -10,8 +10,8 @@ import (
"github.com/go-enry/go-enry/v2"
)
// GetCodeLanguageWithCallback detects code language based on file name and content using callback
func GetCodeLanguageWithCallback(filename string, contentFunc func() ([]byte, error)) string {
// GetCodeLanguage detects code language based on file name and content
func GetCodeLanguage(filename string, content []byte) string {
if language, ok := enry.GetLanguageByExtension(filename); ok {
return language
}
@@ -20,17 +20,9 @@ func GetCodeLanguageWithCallback(filename string, contentFunc func() ([]byte, er
return language
}
content, err := contentFunc()
if err != nil {
if len(content) == 0 {
return enry.OtherLanguage
}
return enry.GetLanguage(filepath.Base(filename), content)
}
// GetCodeLanguage detects code language based on file name and content
func GetCodeLanguage(filename string, content []byte) string {
return GetCodeLanguageWithCallback(filename, func() ([]byte, error) {
return content, nil
})
}

View File

@@ -7,6 +7,7 @@ package context
import (
"fmt"
"net/http"
"net/url"
"strings"
@@ -64,18 +65,22 @@ type APINotFound struct{}
// swagger:response redirect
type APIRedirect struct{}
// Error responses error message to client with given message.
// Error responds with an error message to client with given obj as the message.
// If status is 500, also it prints error to log.
func (ctx *APIContext) Error(status int, title string, obj interface{}) {
var message string
if err, ok := obj.(error); ok {
message = err.Error()
} else {
message = obj.(string)
message = fmt.Sprintf("%s", obj)
}
if status == 500 {
log.Error("%s: %s", title, message)
if status == http.StatusInternalServerError {
log.ErrorWithSkip(1, "%s: %s", title, message)
if macaron.Env == macaron.PROD {
message = ""
}
}
ctx.JSON(status, APIError{
@@ -84,6 +89,22 @@ func (ctx *APIContext) Error(status int, title string, obj interface{}) {
})
}
// InternalServerError responds with an error message to the client with the error as a message
// and the file and line of the caller.
func (ctx *APIContext) InternalServerError(err error) {
log.ErrorWithSkip(1, "InternalServerError: %v", err)
var message string
if macaron.Env != macaron.PROD {
message = err.Error()
}
ctx.JSON(http.StatusInternalServerError, APIError{
Message: message,
URL: setting.API.SwaggerURL,
})
}
func genAPILinks(curURL *url.URL, total, pageSize, curPage int) []string {
page := NewPagination(total, pageSize, curPage, 0)
paginater := page.Paginater

View File

@@ -49,7 +49,9 @@ func Toggle(options *ToggleOptions) macaron.Handler {
if ctx.Req.URL.Path != "/user/settings/change_password" {
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
if ctx.Req.URL.Path != "/user/events" {
ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
}
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
return
}

View File

@@ -103,7 +103,7 @@ func ToPullReviewCommentList(review *models.Review, doer *models.User) ([]*api.P
OrigCommitID: comment.OldRef,
DiffHunk: patch2diff(comment.Patch),
HTMLURL: comment.HTMLURL(),
HTMLPullURL: review.Issue.APIURL(),
HTMLPullURL: review.Issue.HTMLURL(),
}
if comment.Line < 0 {

View File

@@ -6,6 +6,7 @@
package emoji
import (
"sort"
"strings"
"sync"
)
@@ -19,6 +20,7 @@ type Emoji struct {
Description string
Aliases []string
UnicodeVersion string
SkinTones bool
}
var (
@@ -48,6 +50,12 @@ func loadMap() {
// process emoji codes and aliases
codePairs := make([]string, 0)
aliasPairs := make([]string, 0)
// sort from largest to small so we match combined emoji first
sort.Slice(GemojiData, func(i, j int) bool {
return len(GemojiData[i].Emoji) > len(GemojiData[j].Emoji)
})
for i, e := range GemojiData {
if e.Emoji == "" || len(e.Aliases) == 0 {
continue
@@ -72,6 +80,7 @@ func loadMap() {
codeReplacer = strings.NewReplacer(codePairs...)
aliasReplacer = strings.NewReplacer(aliasPairs...)
})
}
// FromCode retrieves the emoji data based on the provided unicode code (ie,
@@ -117,3 +126,22 @@ func ReplaceAliases(s string) string {
loadMap()
return aliasReplacer.Replace(s)
}
// FindEmojiSubmatchIndex returns index pair of longest emoji in a string
func FindEmojiSubmatchIndex(s string) []int {
loadMap()
//see if there are any emoji in string before looking for position of specific ones
//no performance difference when there is a match but 10x faster when there are not
if s == ReplaceCodes(s) {
return nil
}
for j := range GemojiData {
i := strings.Index(s, GemojiData[j].Emoji)
if i != -1 {
return []int{i, i + len(GemojiData[j].Emoji)}
}
}
return nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,6 @@ import (
"bytes"
"io"
"io/ioutil"
"math"
"code.gitea.io/gitea/modules/analyze"
@@ -20,8 +19,22 @@ import (
const fileSizeLimit int64 = 16 * 1024 * 1024
// specialLanguages defines list of languages that are excluded from the calculation
// unless they are the only language present in repository. Only languages which under
// normal circumstances are not considered to be code should be listed here.
var specialLanguages = []string{
"XML",
"JSON",
"TOML",
"YAML",
"INI",
"SVG",
"Text",
"Markdown",
}
// GetLanguageStats calculates language stats for git repository at specified commit
func (repo *Repository) GetLanguageStats(commitID string) (map[string]float32, error) {
func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, error) {
r, err := git.PlainOpen(repo.Path)
if err != nil {
return nil, err
@@ -43,24 +56,32 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]float32, e
}
sizes := make(map[string]int64)
var total int64
err = tree.Files().ForEach(func(f *object.File) error {
if enry.IsVendor(f.Name) || enry.IsDotFile(f.Name) ||
if f.Size == 0 || enry.IsVendor(f.Name) || enry.IsDotFile(f.Name) ||
enry.IsDocumentation(f.Name) || enry.IsConfiguration(f.Name) {
return nil
}
// If content can not be read just do detection by filename
content, _ := readFile(f, fileSizeLimit)
if enry.IsGenerated(f.Name, content) {
return nil
}
// TODO: Use .gitattributes file for linguist overrides
language := analyze.GetCodeLanguageWithCallback(f.Name, func() ([]byte, error) {
return readFile(f, fileSizeLimit)
})
language := analyze.GetCodeLanguage(f.Name, content)
if language == enry.OtherLanguage || language == "" {
return nil
}
// group languages, such as Pug -> HTML; SCSS -> CSS
group := enry.GetLanguageGroup(language)
if group != "" {
language = group
}
sizes[language] += f.Size
total += f.Size
return nil
})
@@ -68,21 +89,14 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]float32, e
return nil, err
}
stats := make(map[string]float32)
var otherPerc float32 = 100
for language, size := range sizes {
perc := float32(math.Round(float64(size)/float64(total)*1000) / 10)
if perc <= 0.1 {
continue
// filter special languages unless they are the only language
if len(sizes) > 1 {
for _, language := range specialLanguages {
delete(sizes, language)
}
otherPerc -= perc
stats[language] = perc
}
otherPerc = float32(math.Round(float64(otherPerc)*10) / 10)
if otherPerc > 0 {
stats["other"] = otherPerc
}
return stats, nil
return sizes, nil
}
func readFile(f *object.File, limit int64) ([]byte, error) {

View File

@@ -34,9 +34,10 @@ func TestRepoStatsIndex(t *testing.T) {
repo, err := models.GetRepositoryByID(1)
assert.NoError(t, err)
status, err := repo.GetIndexerStatus(models.RepoIndexerTypeStats)
assert.NoError(t, err)
assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", status.CommitSha)
langs, err := repo.GetTopLanguageStats(5)
assert.NoError(t, err)
assert.Len(t, langs, 1)
assert.Equal(t, "other", langs[0].Language)
assert.Equal(t, float32(100), langs[0].Percentage)
assert.Empty(t, langs)
}

View File

@@ -65,10 +65,6 @@ var (
// EmojiShortCodeRegex find emoji by alias like :smile:
EmojiShortCodeRegex = regexp.MustCompile(`\:[\w\+\-]+\:{1}`)
// find emoji literal: search all emoji hex range as many times as they appear as
// some emojis (skin color etc..) are just two or more chained together
emojiRegex = regexp.MustCompile(`[\x{1F000}-\x{1FFFF}|\x{2000}-\x{32ff}|\x{fe4e5}-\x{fe4ee}|\x{200D}|\x{FE0F}|\x{e0000}-\x{e007f}]+`)
)
// CSS class for action keywords (e.g. "closes: #1")
@@ -922,8 +918,7 @@ func emojiShortCodeProcessor(ctx *postProcessCtx, node *html.Node) {
// emoji processor to match emoji and add emoji class
func emojiProcessor(ctx *postProcessCtx, node *html.Node) {
m := emojiRegex.FindStringSubmatchIndex(node.Data)
m := emoji.FindEmojiSubmatchIndex(node.Data)
if m == nil {
return
}

View File

@@ -263,7 +263,9 @@ func TestRender_emoji(t *testing.T) {
test(
"Some text with :smile: in the middle",
`<p>Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span> in the middle</p>`)
test(
"Some text with 😄😄 2 emoji next to each other",
`<p>Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span><span class="emoji" aria-label="grinning face with smiling eyes">😄</span> 2 emoji next to each other</p>`)
// should match nothing
test(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",

View File

@@ -151,6 +151,16 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
v.AppendChild(v, newChild)
}
}
case *ast.Text:
if v.SoftLineBreak() && !v.HardLineBreak() {
renderMetas := pc.Get(renderMetasKey).(map[string]string)
mode := renderMetas["mode"]
if mode != "document" {
v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInComments)
} else {
v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInDocuments)
}
}
}
return ast.WalkContinue, nil
})

View File

@@ -29,17 +29,19 @@ var once = sync.Once{}
var urlPrefixKey = parser.NewContextKey()
var isWikiKey = parser.NewContextKey()
var renderMetasKey = parser.NewContextKey()
// NewGiteaParseContext creates a parser.Context with the gitea context set
func NewGiteaParseContext(urlPrefix string, isWiki bool) parser.Context {
func NewGiteaParseContext(urlPrefix string, metas map[string]string, isWiki bool) parser.Context {
pc := parser.NewContext(parser.WithIDs(newPrefixedIDs()))
pc.Set(urlPrefixKey, urlPrefix)
pc.Set(isWikiKey, isWiki)
pc.Set(renderMetasKey, metas)
return pc
}
// RenderRaw renders Markdown to HTML without handling special links.
func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
// render renders Markdown to HTML without handling special links.
func render(body []byte, urlPrefix string, metas map[string]string, wikiMarkdown bool) []byte {
once.Do(func() {
converter = goldmark.New(
goldmark.WithExtensions(extension.Table,
@@ -75,12 +77,9 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
),
)
if setting.Markdown.EnableHardLineBreak {
converter.Renderer().AddOptions(html.WithHardWraps())
}
})
pc := NewGiteaParseContext(urlPrefix, wikiMarkdown)
pc := NewGiteaParseContext(urlPrefix, metas, wikiMarkdown)
var buf bytes.Buffer
if err := converter.Convert(giteautil.NormalizeEOL(body), &buf, parser.WithContext(pc)); err != nil {
log.Error("Unable to render: %v", err)
@@ -112,7 +111,7 @@ func (Parser) Extensions() []string {
// Render implements markup.Parser
func (Parser) Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte {
return RenderRaw(rawBytes, urlPrefix, isWiki)
return render(rawBytes, urlPrefix, metas, isWiki)
}
// Render renders Markdown to HTML with all specific handling stuff.
@@ -120,6 +119,11 @@ func Render(rawBytes []byte, urlPrefix string, metas map[string]string) []byte {
return markup.Render("a.md", rawBytes, urlPrefix, metas)
}
// RenderRaw renders Markdown to HTML without handling special links.
func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
return render(body, urlPrefix, map[string]string{}, wikiMarkdown)
}
// RenderString renders Markdown to HTML with special links and returns string type.
func RenderString(raw, urlPrefix string, metas map[string]string) string {
return markup.RenderString("a.md", raw, urlPrefix, metas)

View File

@@ -47,7 +47,7 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (_ *m
// No need for init mirror.
if !opts.IsMirror {
repoPath := models.RepoPath(u.Name, repo.Name)
if err = initRepository(ctx, repoPath, u, repo, opts); err != nil {
if err = initRepository(ctx, repoPath, doer, repo, opts); err != nil {
if err2 := os.RemoveAll(repoPath); err2 != nil {
log.Error("initRepository: %v", err)
return fmt.Errorf(

View File

@@ -107,10 +107,11 @@ func init() {
// VirtualStore represents a virtual session store implementation.
type VirtualStore struct {
p *VirtualSessionProvider
sid string
lock sync.RWMutex
data map[interface{}]interface{}
p *VirtualSessionProvider
sid string
lock sync.RWMutex
data map[interface{}]interface{}
released bool
}
// NewVirtualStore creates and returns a virtual session store.
@@ -164,7 +165,7 @@ func (s *VirtualStore) Release() error {
// Now ensure that we don't exist!
realProvider := s.p.provider
if realProvider.Exist(s.sid) {
if !s.released && realProvider.Exist(s.sid) {
// This is an error!
return fmt.Errorf("new sid '%s' already exists", s.sid)
}
@@ -172,12 +173,19 @@ func (s *VirtualStore) Release() error {
if err != nil {
return err
}
if err := realStore.Flush(); err != nil {
return err
}
for key, value := range s.data {
if err := realStore.Set(key, value); err != nil {
return err
}
}
return realStore.Release()
err = realStore.Release()
if err == nil {
s.released = true
}
return err
}
return nil
}

View File

@@ -163,7 +163,7 @@ func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, db
// ParseMSSQLHostPort splits the host into host and port
func ParseMSSQLHostPort(info string) (string, string) {
host, port := "127.0.0.1", "1433"
host, port := "127.0.0.1", "0"
if strings.Contains(info, ":") {
host = strings.Split(info, ":")[0]
port = strings.Split(info, ":")[1]

View File

@@ -256,12 +256,14 @@ var (
// Markdown settings
Markdown = struct {
EnableHardLineBreak bool
CustomURLSchemes []string `ini:"CUSTOM_URL_SCHEMES"`
FileExtensions []string
EnableHardLineBreakInComments bool
EnableHardLineBreakInDocuments bool
CustomURLSchemes []string `ini:"CUSTOM_URL_SCHEMES"`
FileExtensions []string
}{
EnableHardLineBreak: true,
FileExtensions: strings.Split(".md,.markdown,.mdown,.mkd", ","),
EnableHardLineBreakInComments: true,
EnableHardLineBreakInDocuments: false,
FileExtensions: strings.Split(".md,.markdown,.mdown,.mkd", ","),
}
// Admin settings
@@ -728,6 +730,8 @@ func NewContext() {
for _, key := range minimumKeySizes {
if key.MustInt() != -1 {
SSH.MinimumKeySizes[strings.ToLower(key.Name())] = key.MustInt()
} else {
delete(SSH.MinimumKeySizes, strings.ToLower(key.Name()))
}
}
SSH.AuthorizedKeysBackup = sec.Key("SSH_AUTHORIZED_KEYS_BACKUP").MustBool(true)
@@ -999,15 +1003,15 @@ func NewContext() {
if len(Langs) == 0 {
Langs = []string{
"en-US", "zh-CN", "zh-HK", "zh-TW", "de-DE", "fr-FR", "nl-NL", "lv-LV",
"ru-RU", "uk-UA", "ja-JP", "es-ES", "pt-BR", "pl-PL", "bg-BG", "it-IT",
"fi-FI", "tr-TR", "cs-CZ", "sr-SP", "sv-SE", "ko-KR"}
"ru-RU", "uk-UA", "ja-JP", "es-ES", "pt-BR", "pt-PT", "pl-PL", "bg-BG",
"it-IT", "fi-FI", "tr-TR", "cs-CZ", "sr-SP", "sv-SE", "ko-KR"}
}
Names = Cfg.Section("i18n").Key("NAMES").Strings(",")
if len(Names) == 0 {
Names = []string{"English", "简体中文", "繁體中文(香港)", "繁體中文(台灣)", "Deutsch",
"français", "Nederlands", "latviešu", "русский", "Українська", "日本語",
"español", "português do Brasil", "polski", "български", "italiano",
"suomi", "Türkçe", "čeština", "српски", "svenska", "한국어"}
"español", "português do Brasil", "Português de Portugal", "polski", "български",
"italiano", "suomi", "Türkçe", "čeština", "српски", "svenska", "한국어"}
}
dateLangs = Cfg.Section("i18n.datelang").KeysHash()
@@ -1069,7 +1073,7 @@ func loadInternalToken(sec *ini.Section) string {
return token
}
return string(buf)
return strings.TrimSpace(string(buf))
default:
log.Fatal("Unsupported URI-Scheme %q (INTERNAL_TOKEN_URI = %q)", tempURI.Scheme, uri)
}

View File

@@ -82,6 +82,7 @@ type CreatePullRequestOption struct {
type EditPullRequestOption struct {
Title string `json:"title"`
Body string `json:"body"`
Base string `json:"base"`
Assignee string `json:"assignee"`
Assignees []string `json:"assignees"`
Milestone int64 `json:"milestone"`

View File

@@ -48,18 +48,6 @@ func JSONRenderer() macaron.Handler {
})
}
// JSRenderer implements the macaron handler for serving JS templates.
func JSRenderer() macaron.Handler {
return macaron.Renderer(macaron.RenderOptions{
Funcs: NewFuncMap(),
Directory: path.Join(setting.StaticRootPath, "templates"),
AppendDirectories: []string{
path.Join(setting.CustomPath, "templates"),
},
HTMLContentType: "application/javascript",
})
}
// Mailer provides the templates required for sending notification mails.
func Mailer() (*texttmpl.Template, *template.Template) {
for _, funcs := range NewTextFuncMap() {

View File

@@ -132,15 +132,6 @@ func JSONRenderer() macaron.Handler {
})
}
// JSRenderer implements the macaron handler for serving JS templates.
func JSRenderer() macaron.Handler {
return macaron.Renderer(macaron.RenderOptions{
Funcs: NewFuncMap(),
TemplateFileSystem: NewTemplateFileSystem(),
HTMLContentType: "application/javascript",
})
}
// Mailer provides the templates required for sending notification mails.
func Mailer() (*texttmpl.Template, *template.Template) {
for _, funcs := range NewTextFuncMap() {

View File

@@ -75,6 +75,11 @@ func (ts TimeStamp) FormatShort() string {
return ts.Format("Jan 02, 2006")
}
// FormatDate formats a date in YYYY-MM-DD server time zone
func (ts TimeStamp) FormatDate() string {
return time.Unix(int64(ts), 0).String()[:10]
}
// IsZero is zero time
func (ts TimeStamp) IsZero() bool {
return ts.AsTimeInLocation(time.Local).IsZero()

View File

@@ -25,6 +25,7 @@ Damaris Padieu <damizx AT hotmail DOT fr>
Daniel Speichert <daniel AT speichert DOT pl>
David Yzaguirre <dvdyzag AT gmail DOT com>
Dmitriy Nogay <me AT catwhocode DOT ga>
Emanuel Angelo <emanuel DOT angelo AT gmail DOT com>
Enrico Testori hypertesto AT gmail DOT com
Ezequiel Gonzalez Rial <gonrial AT gmail DOT com>
Gabriel Dugny <gabriel DOT dugny AT gmail DOT com>

View File

@@ -1647,6 +1647,7 @@ diff.review.placeholder = Review comment
diff.review.comment = Comment
diff.review.approve = Approve
diff.review.reject = Request changes
diff.committed_by = committed by
releases.desc = Track project versions and downloads.
release.releases = Releases
@@ -1872,7 +1873,6 @@ dashboard.resync_all_sshkeys.desc = (Not needed for the built-in SSH server.)
dashboard.resync_all_hooks = Resynchronize pre-receive, update and post-receive hooks of all repositories.
dashboard.reinit_missing_repos = Reinitialize all missing Git repositories for which records exist
dashboard.sync_external_users = Synchronize external user data
dashboard.git_fsck = Execute health checks on all repositories
dashboard.server_uptime = Server Uptime
dashboard.current_goroutine = Current Goroutines
dashboard.current_memory_usage = Current Memory Usage

22
package-lock.json generated
View File

@@ -14852,6 +14852,28 @@
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
},
"workbox-core": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-5.1.3.tgz",
"integrity": "sha512-TFSIPxxciX9sFaj0FDiohBeIKpwMcCyNduydi9i3LChItcndDS6TJpErxybv8aBWeCMraXt33TWtF6kKuIObNw=="
},
"workbox-routing": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-5.1.3.tgz",
"integrity": "sha512-F+sAp9Iy3lVl3BEG+pzXWVq4AftzjiFpHDaZ4Kf4vLoBoKQE0hIHet4zE5DpHqYdyw+Udhp4wrfHamX6PN6z1Q==",
"requires": {
"workbox-core": "^5.1.3"
}
},
"workbox-strategies": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-5.1.3.tgz",
"integrity": "sha512-wiXHfmOKnWABeIVW+/ye0e00+2CcS5y7SIj2f9zcdy2ZLEbcOf7B+yOl5OrWpBGlTUwRjIYhV++ZqiKm3Dc+8w==",
"requires": {
"workbox-core": "^5.1.3",
"workbox-routing": "^5.1.3"
}
},
"worker-farm": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",

View File

@@ -47,6 +47,8 @@
"webpack": "4.43.0",
"webpack-cli": "3.3.11",
"webpack-fix-style-only-entries": "0.4.0",
"workbox-routing": "5.1.3",
"workbox-strategies": "5.1.3",
"worker-loader": "2.0.0"
},
"devDependencies": {

View File

@@ -48,10 +48,12 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) {
}
switch form.Mode {
case "comment":
fallthrough
case "gfm":
md := []byte(form.Text)
urlPrefix := form.Context
var meta map[string]string
meta := map[string]string{}
if !strings.HasPrefix(setting.AppSubURL+"/", urlPrefix) {
// check if urlPrefix is already set to a URL
linkRegex, _ := xurls.StrictMatchingScheme("https?://")
@@ -61,7 +63,15 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) {
}
}
if ctx.Repo != nil && ctx.Repo.Repository != nil {
meta = ctx.Repo.Repository.ComposeMetas()
// "gfm" = Github Flavored Markdown - set this to render as a document
if form.Mode == "gfm" {
meta = ctx.Repo.Repository.ComposeDocumentMetas()
} else {
meta = ctx.Repo.Repository.ComposeMetas()
}
}
if form.Mode == "gfm" {
meta["mode"] = "document"
}
if form.Wiki {
_, err := ctx.Write([]byte(markdown.RenderWiki(md, urlPrefix, meta)))

View File

@@ -94,7 +94,7 @@ Here are some links to the most important topics. You can find the full list of
<p><strong>Wine Staging</strong> on website <a href="http://wine-staging.com" rel="nofollow">wine-staging.com</a>.</p>
<h2 id="user-content-quick-links">Quick Links</h2>
<p>Here are some links to the most important topics. You can find the full list of pages at the sidebar.</p>
<p><a href="` + AppSubURL + `wiki/Configuration" rel="nofollow">Configuration</a><br/>
<p><a href="` + AppSubURL + `wiki/Configuration" rel="nofollow">Configuration</a>
<a href="` + AppSubURL + `wiki/raw/images/icon-bug.png" rel="nofollow"><img src="` + AppSubURL + `wiki/raw/images/icon-bug.png" title="icon-bug.png" alt="images/icon-bug.png"/></a></p>
`,
// Guard wiki sidebar: special syntax

View File

@@ -7,6 +7,7 @@ package repo
import (
"encoding/base64"
"fmt"
"net/http"
"time"
@@ -198,6 +199,16 @@ func CreateFile(ctx *context.APIContext, apiOpts api.CreateFileOptions) {
// responses:
// "201":
// "$ref": "#/responses/FileResponse"
// "403":
// "$ref": "#/responses/error"
// "404":
// "$ref": "#/responses/notFound"
// "422":
// "$ref": "#/responses/error"
if ctx.Repo.Repository.IsEmpty {
ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty"))
}
if apiOpts.BranchName == "" {
apiOpts.BranchName = ctx.Repo.Repository.DefaultBranch
@@ -235,7 +246,7 @@ func CreateFile(ctx *context.APIContext, apiOpts api.CreateFileOptions) {
}
if fileResponse, err := createOrUpdateFile(ctx, opts); err != nil {
ctx.Error(http.StatusInternalServerError, "CreateFile", err)
handleCreateOrUpdateFileError(ctx, err)
} else {
ctx.JSON(http.StatusCreated, fileResponse)
}
@@ -274,6 +285,16 @@ func UpdateFile(ctx *context.APIContext, apiOpts api.UpdateFileOptions) {
// responses:
// "200":
// "$ref": "#/responses/FileResponse"
// "403":
// "$ref": "#/responses/error"
// "404":
// "$ref": "#/responses/notFound"
// "422":
// "$ref": "#/responses/error"
if ctx.Repo.Repository.IsEmpty {
ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty"))
}
if apiOpts.BranchName == "" {
apiOpts.BranchName = ctx.Repo.Repository.DefaultBranch
@@ -313,12 +334,30 @@ func UpdateFile(ctx *context.APIContext, apiOpts api.UpdateFileOptions) {
}
if fileResponse, err := createOrUpdateFile(ctx, opts); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateFile", err)
handleCreateOrUpdateFileError(ctx, err)
} else {
ctx.JSON(http.StatusOK, fileResponse)
}
}
func handleCreateOrUpdateFileError(ctx *context.APIContext, err error) {
if models.IsErrUserCannotCommit(err) || models.IsErrFilePathProtected(err) {
ctx.Error(http.StatusForbidden, "Access", err)
return
}
if models.IsErrBranchAlreadyExists(err) || models.IsErrFilenameInvalid(err) || models.IsErrSHADoesNotMatch(err) ||
models.IsErrFilePathInvalid(err) || models.IsErrRepoFileAlreadyExists(err) {
ctx.Error(http.StatusUnprocessableEntity, "Invalid", err)
return
}
if git.IsErrBranchNotExist(err) {
ctx.Error(http.StatusNotFound, "BranchDoesNotExist", err)
return
}
ctx.Error(http.StatusInternalServerError, "UpdateFile", err)
}
// Called from both CreateFile or UpdateFile to handle both
func createOrUpdateFile(ctx *context.APIContext, opts *repofiles.UpdateRepoFileOptions) (*api.FileResponse, error) {
if !canWriteFiles(ctx.Repo) {

View File

@@ -691,7 +691,7 @@ func UpdateIssueDeadline(ctx *context.APIContext, form api.EditDeadlineOption) {
var deadline time.Time
if form.Deadline != nil && !form.Deadline.IsZero() {
deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(),
23, 59, 59, 0, form.Deadline.Location())
23, 59, 59, 0, time.Local)
deadlineUnix = timeutil.TimeStamp(deadline.Unix())
}

View File

@@ -382,6 +382,8 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
// "$ref": "#/responses/PullRequest"
// "403":
// "$ref": "#/responses/forbidden"
// "409":
// "$ref": "#/responses/error"
// "412":
// "$ref": "#/responses/error"
// "422":
@@ -508,6 +510,30 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
notification.NotifyIssueChangeStatus(ctx.User, issue, statusChangeComment, issue.IsClosed)
}
// change pull target branch
if len(form.Base) != 0 && form.Base != pr.BaseBranch {
if !ctx.Repo.GitRepo.IsBranchExist(form.Base) {
ctx.Error(http.StatusNotFound, "NewBaseBranchNotExist", fmt.Errorf("new base '%s' not exist", form.Base))
return
}
if err := pull_service.ChangeTargetBranch(pr, ctx.User, form.Base); err != nil {
if models.IsErrPullRequestAlreadyExists(err) {
ctx.Error(http.StatusConflict, "IsErrPullRequestAlreadyExists", err)
return
} else if models.IsErrIssueIsClosed(err) {
ctx.Error(http.StatusUnprocessableEntity, "IsErrIssueIsClosed", err)
return
} else if models.IsErrPullRequestHasMerged(err) {
ctx.Error(http.StatusConflict, "IsErrPullRequestHasMerged", err)
return
} else {
ctx.InternalServerError(err)
}
return
}
notification.NotifyPullRequestChangeTargetBranch(ctx.User, pr, form.Base)
}
// Refetch from database
pr, err = models.GetPullRequestByIndex(ctx.Repo.Repository.ID, pr.Index)
if err != nil {

View File

@@ -78,9 +78,9 @@ func Search(ctx *context.APIContext) {
// in: query
// description: include private repositories this user has access to (defaults to true)
// type: boolean
// - name: onlyPrivate
// - name: is_private
// in: query
// description: only include private repositories this user has access to (defaults to false)
// description: show only pubic, private or all repositories (defaults to all)
// type: boolean
// - name: template
// in: query
@@ -133,7 +133,6 @@ func Search(ctx *context.APIContext) {
TopicOnly: ctx.QueryBool("topic"),
Collaborate: util.OptionalBoolNone,
Private: ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")),
OnlyPrivate: ctx.IsSigned && ctx.QueryBool("onlyPrivate"),
Template: util.OptionalBoolNone,
StarredByID: ctx.QueryInt64("starredBy"),
IncludeDescription: ctx.QueryBool("includeDesc"),
@@ -169,6 +168,10 @@ func Search(ctx *context.APIContext) {
opts.Archived = util.OptionalBoolOf(ctx.QueryBool("archived"))
}
if ctx.Query("is_private") != "" {
opts.IsPrivate = util.OptionalBoolOf(ctx.QueryBool("is_private"))
}
var sortMode = ctx.Query("sort")
if len(sortMode) > 0 {
var sortOrder = ctx.Query("order")

View File

@@ -144,6 +144,8 @@ func CreateGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption) {
// responses:
// "201":
// "$ref": "#/responses/GPGKey"
// "404":
// "$ref": "#/responses/notFound"
// "422":
// "$ref": "#/responses/validationError"
@@ -169,6 +171,8 @@ func DeleteGPGKey(ctx *context.APIContext) {
// "$ref": "#/responses/empty"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
if err := models.DeleteGPGKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
if models.IsErrGPGKeyAccessDenied(err) {
@@ -186,9 +190,13 @@ func DeleteGPGKey(ctx *context.APIContext) {
func HandleAddGPGKeyError(ctx *context.APIContext, err error) {
switch {
case models.IsErrGPGKeyAccessDenied(err):
ctx.Error(http.StatusUnprocessableEntity, "", "You do not have access to this GPG key")
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyAccessDenied", "You do not have access to this GPG key")
case models.IsErrGPGKeyIDAlreadyUsed(err):
ctx.Error(http.StatusUnprocessableEntity, "", "A key with the same id already exists")
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyIDAlreadyUsed", "A key with the same id already exists")
case models.IsErrGPGKeyParsing(err):
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyParsing", err)
case models.IsErrGPGNoEmailFound(err):
ctx.Error(http.StatusNotFound, "GPGNoEmailFound", err)
default:
ctx.Error(http.StatusInternalServerError, "AddGPGKey", err)
}

View File

@@ -194,7 +194,6 @@ func RenderUserSearch(ctx *context.Context, opts *models.SearchUserOptions, tplN
if opts.Page <= 1 {
opts.Page = 1
}
opts.Actor = ctx.User
var (
users []*models.User
@@ -252,6 +251,7 @@ func ExploreUsers(ctx *context.Context) {
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
RenderUserSearch(ctx, &models.SearchUserOptions{
Actor: ctx.User,
Type: models.UserTypeIndividual,
ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum},
IsActive: util.OptionalBoolTrue,
@@ -272,6 +272,7 @@ func ExploreOrganizations(ctx *context.Context) {
}
RenderUserSearch(ctx, &models.SearchUserOptions{
Actor: ctx.User,
Type: models.UserTypeOrganization,
ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum},
Visible: visibleTypes,

View File

@@ -29,6 +29,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
repo_service "code.gitea.io/gitea/services/repository"
)
@@ -135,6 +136,16 @@ func HTTP(ctx *context.Context) {
environ []string
)
// don't allow anonymous pulls if organization is not public
if isPublicPull {
if err := repo.GetOwner(); err != nil {
ctx.ServerError("GetOwner", err)
return
}
askAuth = askAuth || (repo.Owner.Visibility != structs.VisibleTypePublic)
}
// check access
if askAuth {
authUsername = ctx.Req.Header.Get(setting.ReverseProxyAuthUser)

View File

@@ -22,6 +22,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/routers/utils"
@@ -75,7 +76,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
ctx.Repo.GitRepo.Close()
ctx.Repo.GitRepo = nil
}
if err := repo_service.ChangeRepositoryName(ctx.Repo.Owner, repo, newRepoName); err != nil {
if err := repo_service.ChangeRepositoryName(ctx.User, repo, newRepoName); err != nil {
ctx.Data["Err_RepoName"] = true
switch {
case models.IsErrRepoAlreadyExist(err):
@@ -379,6 +380,14 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
return
}
if newOwner.Type == models.UserTypeOrganization {
if !ctx.User.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !ctx.User.IsUserPartOfOrg(newOwner.ID) {
// The user shouldn't know about this organization
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil)
return
}
}
// Close the GitRepo if open
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()

View File

@@ -319,7 +319,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
if markupType := markup.Type(readmeFile.name); markupType != "" {
ctx.Data["IsMarkup"] = true
ctx.Data["MarkupType"] = string(markupType)
ctx.Data["FileContent"] = string(markup.Render(readmeFile.name, buf, readmeTreelink, ctx.Repo.Repository.ComposeMetas()))
ctx.Data["FileContent"] = string(markup.Render(readmeFile.name, buf, readmeTreelink, ctx.Repo.Repository.ComposeDocumentMetas()))
} else {
ctx.Data["IsRenderedHTML"] = true
ctx.Data["FileContent"] = strings.Replace(
@@ -459,7 +459,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
if markupType := markup.Type(blob.Name()); markupType != "" {
ctx.Data["IsMarkup"] = true
ctx.Data["MarkupType"] = markupType
ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeDocumentMetas()))
} else if readmeExist {
ctx.Data["IsRenderedHTML"] = true
ctx.Data["FileContent"] = strings.Replace(
@@ -538,7 +538,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
buf = append(buf, d...)
ctx.Data["IsMarkup"] = true
ctx.Data["MarkupType"] = markupType
ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeDocumentMetas()))
}
}

View File

@@ -209,7 +209,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
return nil, nil
}
metas := ctx.Repo.Repository.ComposeMetas()
metas := ctx.Repo.Repository.ComposeDocumentMetas()
ctx.Data["content"] = markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
ctx.Data["sidebarPresent"] = sidebarContent != nil
ctx.Data["sidebarContent"] = markdown.RenderWiki(sidebarContent, ctx.Repo.RepoLink, metas)

View File

@@ -1048,10 +1048,6 @@ func RegisterRoutes(m *macaron.Macaron) {
ctx.HTML(200, "pwa/manifest_json")
})
m.Get("/serviceworker.js", templates.JSRenderer(), func(ctx *context.Context) {
ctx.HTML(200, "pwa/serviceworker_js")
})
// prometheus metrics endpoint
if setting.Metrics.Enabled {
c := metrics.NewCollector()

View File

@@ -1489,6 +1489,7 @@ func ResetPasswdPost(ctx *context.Context) {
func MustChangePassword(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/settings/change_password"
ctx.Data["MustChangePassword"] = true
ctx.HTML(200, tplMustChangePassword)
}

View File

@@ -15,7 +15,7 @@
{{.i18n.Tr "admin.dashboard.operations"}}
</h4>
<div class="ui attached table segment">
<form method="post" action="{{.AppSubUrl}}/admin">
<form method="post" action="{{AppSubUrl}}/admin">
{{.CsrfTokenHtml}}
<table class="ui very basic table">
<tbody>
@@ -53,8 +53,8 @@
<td><button type="submit" class="ui green button" name="op" value="sync_external_users">{{svg "octicon-triangle-right" 16}} {{.i18n.Tr "admin.dashboard.operation_run"}}</button></td>
</tr>
<tr>
<td>{{.i18n.Tr "admin.dashboard.git_fsck"}}</td>
<td><button type="submit" class="ui green button" name="op" value="git_fsck">{{svg "octicon-triangle-right" 16}} {{.i18n.Tr "admin.dashboard.operation_run"}}</button></td>
<td>{{.i18n.Tr "admin.dashboard.repo_health_check"}}</td>
<td><button type="submit" class="ui green button" name="op" value="repo_health_check">{{svg "octicon-triangle-right" 16}} {{.i18n.Tr "admin.dashboard.operation_run"}}</button></td>
</tr>
<tr>
<td>{{.i18n.Tr "admin.dashboard.delete_generated_repository_avatars"}}</td>

View File

@@ -26,6 +26,8 @@
<img class="img-13" src="{{StaticUrlPrefix}}/img/msteams.png">
{{else if eq .HookType "feishu"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/feishu.png">
{{else if eq .HookType "matrix"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/matrix.svg">
{{end}}
</div>
</h4>
@@ -38,6 +40,7 @@
{{template "repo/settings/webhook/telegram" .}}
{{template "repo/settings/webhook/msteams" .}}
{{template "repo/settings/webhook/feishu" .}}
{{template "repo/settings/webhook/matrix" .}}
</div>
{{template "repo/settings/webhook/history" .}}

View File

@@ -7,7 +7,7 @@
{{.i18n.Tr "admin.monitor.cron"}}
</h4>
<div class="ui attached table segment">
<form method="post" action="{{.AppSubUrl}}/admin">
<form method="post" action="{{AppSubUrl}}/admin">
{{.CsrfTokenHtml}}
<table class="ui very basic striped table">
<thead>

View File

@@ -7,7 +7,7 @@
{{.i18n.Tr "admin.notices.system_notice_list"}} ({{.i18n.Tr "admin.total" .Total}})
</h4>
<div class="ui attached table segment">
<table class="ui very basic select selectable table">
<table id="notice-table" class="ui very basic select selectable table">
<thead>
<tr>
<th></th>
@@ -28,9 +28,9 @@
</td>
<td>{{.ID}}</td>
<td>{{$.i18n.Tr .TrStr}}</td>
<td>{{SubStr .Description 0 120}}...</td>
<td><span class="poping up" data-content="{{.CreatedUnix.AsTime}}" data-variation="inverted tiny">{{.CreatedUnix.FormatShort}}</span></td>
<td><a href="#"><i class="browser icon view-detail" data-content="{{.Description}}"></i></a></td>
<td class="view-detail"><span class="notice-description text truncate">{{.Description}}</span></td>
<td><span class="notice-created-time poping up" data-content="{{.CreatedUnix.AsTime}}" data-variation="inverted tiny">{{.CreatedUnix.FormatShort}}</span></td>
<td><a href="#"><i class="browser icon view-detail"></i></a></td>
</tr>
{{end}}
</tbody>
@@ -73,10 +73,11 @@
</div>
</div>
<div class="ui modal" id="detail-modal">
<div class="ui modal admin" id="detail-modal">
<i class="close icon"></i>
<div class="header">{{$.i18n.Tr "admin.notices.view_detail_header"}}</div>
<div class="content">
<div class="sub header"></div>
<pre></pre>
</div>
</div>

View File

@@ -6,30 +6,6 @@
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>{{if .Title}}{{.Title | RenderEmojiPlain}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}} </title>
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials">
{{if UseServiceWorker}}
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) {
// Registration was successful
console.info('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.info('ServiceWorker registration failed: ', err);
});
}
</script>
{{else}}
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then(function(registrations) {
registrations.forEach(function(registration) {
registration.unregister();
console.info('ServiceWorker unregistered');
});
});
}
</script>
{{end}}
<meta name="theme-color" content="{{ThemeColorMetaTag}}">
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" />
<meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" />
@@ -84,8 +60,10 @@
</script>
<script>
window.config = {
AppVer: '{{AppVer}}',
AppSubUrl: '{{AppSubUrl}}',
StaticUrlPrefix: '{{StaticUrlPrefix}}',
UseServiceWorker: {{UseServiceWorker}},
csrf: '{{.CsrfToken}}',
HighlightJS: {{if .RequireHighlightJS}}true{{else}}false{{end}},
Minicolors: {{if .RequireMinicolors}}true{{else}}false{{end}},
@@ -114,8 +92,6 @@
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/gitea-safari.svg" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2" type="font/woff2" crossorigin="anonymous">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/outline-icons.woff2" type="font/woff2" crossorigin="anonymous">
{{if .RequireSimpleMDE}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css">
{{end}}

View File

@@ -8,7 +8,9 @@
</div>
</div>
{{if .IsSigned}}
{{if and .IsSigned .MustChangePassword}}
{{/* No links */}}
{{else if .IsSigned}}
<a class="item {{if .PageIsDashboard}}active{{end}}" href="{{AppSubUrl}}/">{{.i18n.Tr "dashboard"}}</a>
{{if not .UnitIssuesGlobalDisabled}}
<a class="item {{if .PageIsIssues}}active{{end}}" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a>
@@ -40,7 +42,30 @@
</div>
*/}}
{{if .IsSigned}}
{{if and .IsSigned .MustChangePassword}}
<div class="right stackable menu">
<div class="ui dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted">
<span class="text">
<img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}">
<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span>
<span class="mobile-only">{{.SignedUser.Name}}</span>
<span class="fitted not-mobile" tabindex="-1">{{svg "octicon-triangle-down" 16}}</span>
</span>
<div class="menu user-menu" tabindex="-1">
<div class="ui header">
{{.i18n.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
</div>
<div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout" data-redirect="{{AppSubUrl}}/">
{{svg "octicon-sign-out" 16}}
{{.i18n.Tr "sign_out"}}<!-- Sign Out -->
</a>
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
</div>
{{else if .IsSigned}}
<div class="right stackable menu">
<a href="{{AppSubUrl}}/notifications" class="item poping up" data-content='{{.i18n.Tr "notifications"}}' data-variation="tiny inverted">
<span class="text">
@@ -121,9 +146,7 @@
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
</div><!-- end signed user right menu -->
{{else}}
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a>
<div class="right stackable menu">
{{if .ShowRegistrationButton}}
@@ -135,6 +158,5 @@
{{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}}
</a>
</div><!-- end anonymous right menu -->
{{end}}
</div>

View File

@@ -25,6 +25,8 @@
<img class="img-13" src="{{StaticUrlPrefix}}/img/msteams.png">
{{else if eq .HookType "feishu"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/feishu.png">
{{else if eq .HookType "matrix"}}
<img class="img-13" src="{{StaticUrlPrefix}}/img/matrix.svg">
{{end}}
</div>
</h4>
@@ -37,6 +39,7 @@
{{template "repo/settings/webhook/telegram" .}}
{{template "repo/settings/webhook/msteams" .}}
{{template "repo/settings/webhook/feishu" .}}
{{template "repo/settings/webhook/matrix" .}}
</div>
{{template "repo/settings/webhook/history" .}}

View File

@@ -1,83 +0,0 @@
var STATIC_CACHE = 'static-cache-v1';
var urlsToCache = [
// js
'{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}',
'{{StaticUrlPrefix}}/js/clipboard.js',
'{{StaticUrlPrefix}}/js/gitgraph.js',
'{{StaticUrlPrefix}}/js/highlight.js',
'{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}',
'{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}',
'{{StaticUrlPrefix}}/js/swagger.js?v={{MD5 AppVer}}',
'{{StaticUrlPrefix}}/js/dropzone.js',
'{{StaticUrlPrefix}}/js/datetimepicker.js',
'{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js',
'{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js',
'{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js',
'{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js',
// css
'{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}',
'{{StaticUrlPrefix}}/css/swagger.css?v={{MD5 AppVer}}',
'{{StaticUrlPrefix}}/css/dropzone.css',
'{{StaticUrlPrefix}}/css/datetimepicker.css',
'{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}',
'{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css',
'{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css',
'{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css',
'{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css',
{{if .IsSigned }}
{{ if ne .SignedUser.Theme "gitea" }}
'{{StaticUrlPrefix}}/css/theme-{{.SignedUser.Theme}}.css?v={{MD5 AppVer}}',
{{end}}
{{else if ne DefaultTheme "gitea"}}
'{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css?v={{MD5 AppVer}}',
{{end}}
// img
'{{StaticUrlPrefix}}/img/gitea-sm.png',
'{{StaticUrlPrefix}}/img/gitea-lg.png',
// svg
'{{StaticUrlPrefix}}/img/svg/icons.svg',
// fonts
'{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2',
'{{StaticUrlPrefix}}/vendor/assets/roboto-fonts/roboto-v20-latin-ext_cyrillic-ext_latin_greek_vietnamese_cyrillic_greek-ext-regular.woff2',
'{{StaticUrlPrefix}}/vendor/assets/roboto-fonts/roboto-v20-latin-ext_cyrillic-ext_latin_greek_vietnamese_cyrillic_greek-ext-italic.woff2',
'{{StaticUrlPrefix}}/vendor/assets/roboto-fonts/roboto-v20-latin-ext_cyrillic-ext_latin_greek_vietnamese_cyrillic_greek-ext-700.woff2',
'{{StaticUrlPrefix}}/vendor/assets/roboto-fonts/roboto-v20-latin-ext_cyrillic-ext_latin_greek_vietnamese_cyrillic_greek-ext-700italic.woff2',
// monaco
'{{StaticUrlPrefix}}/css/monaco.css',
'{{StaticUrlPrefix}}/fonts/codicon.ttf',
'{{StaticUrlPrefix}}/js/monaco-css.worker.js',
'{{StaticUrlPrefix}}/js/monaco-editor.worker.js',
'{{StaticUrlPrefix}}/js/monaco-html.worker.js',
'{{StaticUrlPrefix}}/js/monaco-json.worker.js',
'{{StaticUrlPrefix}}/js/monaco.js',
'{{StaticUrlPrefix}}/js/monaco-ts.worker.js'
];
self.addEventListener('install', function (event) {
// Perform install steps
event.waitUntil(
caches.open(STATIC_CACHE)
.then(function (cache) {
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request)
.then(function (response) {
// Cache hit - return response
if (response) {
return response;
}
return fetch(event.request);
}
)
);
});

View File

@@ -31,7 +31,7 @@
</div>
<div class="ui attached info segment {{$class}}">
<div class="ui stackable grid">
<div class="ten wide column">
<div class="nine wide column">
{{if .Author}}
<img class="ui avatar image" src="{{.Author.RelAvatarLink}}" />
{{if .Author.FullName}}
@@ -43,19 +43,22 @@
<img class="ui avatar image" src="{{AvatarLink .Commit.Author.Email}}" />
<strong>{{.Commit.Author.Name}}</strong>
{{end}}
{{if or (ne .Commit.Committer.Name .Commit.Author.Name) (ne .Commit.Committer.Email .Commit.Author.Email)}}
<span> </span>
{{if ne .Verification.CommittingUser.ID 0}}
<img class="ui avatar image" src="{{.Verification.CommittingUser.RelAvatarLink}}" />
<a href="{{.Verification.CommittingUser.HomeLink}}"><strong>{{.Commit.Committer.Name}}</strong> &lt;{{.Commit.Committer.Email}}&gt;</a>
{{else}}
<img class="ui avatar image" src="{{AvatarLink .Commit.Committer.Email}}" />
<strong>{{.Commit.Committer.Name}}</strong>
{{end}}
{{end}}
<span class="text grey" id="authored-time">{{TimeSince .Commit.Author.When $.Lang}}</span>
{{if or (ne .Commit.Committer.Name .Commit.Author.Name) (ne .Commit.Committer.Email .Commit.Author.Email)}}
<div class="committed-by">
<span class="text grey">{{svg "octicon-git-commit" 16}}{{.i18n.Tr "repo.diff.committed_by"}}</span>
{{if ne .Verification.CommittingUser.ID 0}}
<img class="ui avatar image" src="{{.Verification.CommittingUser.RelAvatarLink}}" />
<a href="{{.Verification.CommittingUser.HomeLink}}"><strong>{{.Commit.Committer.Name}}</strong> &lt;{{.Commit.Committer.Email}}&gt;</a>
{{else}}
<img class="ui avatar image" src="{{AvatarLink .Commit.Committer.Email}}" />
<strong>{{.Commit.Committer.Name}}</strong>
{{end}}
</div>
{{end}}
</div>
<div class="six wide right aligned column">
<div class="seven wide right aligned column">
<div class="ui horizontal list">
{{if .Parents}}
<div class="item">

View File

@@ -2,7 +2,7 @@
{{if $.hidden}}
<button class="comment-form-reply ui green labeled icon tiny button"><i class="reply icon"></i> {{$.root.i18n.Tr "repo.diff.comment.reply"}}</button>
{{end}}
<form class="ui form {{if $.hidden}}hide{{end}} comment-form comment-form-reply" action="{{$.root.Issue.HTMLURL}}/files/reviews/comments" method="post">
<form class="ui form {{if $.hidden}}hide comment-form comment-form-reply{{end}}" action="{{$.root.Issue.HTMLURL}}/files/reviews/comments" method="post">
{{$.root.CsrfTokenHtml}}
<input type="hidden" name="latest_commit_id" value="{{$.root.AfterCommitID}}"/>
<input type="hidden" name="side" value="{{if $.Side}}{{$.Side}}{{end}}">

View File

@@ -31,7 +31,7 @@
{{end}}
{{end}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID) }}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $.root "item" . "delete" true "diff" true }}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $.root "item" . "delete" true "diff" true "IsCommentPoster" (and $.root.IsSigned (eq $.root.SignedUserID .PosterID))}}
</div>
</div>
<div class="ui attached segment">

View File

@@ -30,7 +30,7 @@
<div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
<a class="active item" data-tab="write">{{svg "octicon-code" 16}} {{if .IsNewFile}}{{.i18n.Tr "repo.editor.new_file"}}{{else}}{{.i18n.Tr "repo.editor.edit_file"}}{{end}}</a>
{{if not .IsNewFile}}
<a class="item" data-tab="preview" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}">{{svg "octicon-eye" 16}} {{.i18n.Tr "preview"}}</a>
<a class="item" data-tab="preview" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}/src/{{.BranchNameSubURL | EscapePound}}" data-preview-file-modes="{{.PreviewableFileModes}}" data-markdown-mode="gfm">{{svg "octicon-eye" 16}} {{.i18n.Tr "preview"}}</a>
<a class="item" data-tab="diff" data-url="{{.RepoLink}}/_preview/{{.BranchName | EscapePound}}/{{.TreePath | EscapePound}}" data-context="{{.BranchLink}}">{{svg "octicon-diff" 16}} {{.i18n.Tr "repo.editor.preview_changes"}}</a>
{{end}}
</div>

View File

@@ -41,7 +41,7 @@
{{if not $.Repository.IsArchived}}
<div class="ui right actions">
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)}}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" .Issue "delete" false "diff" false }}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" .Issue "delete" false "diff" false "IsCommentPoster" $.IsIssuePoster}}
</div>
{{end}}
</div>

View File

@@ -38,7 +38,7 @@
</div>
{{end}}
{{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "diff" false }}
{{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
</div>
{{end}}
</div>

View File

@@ -10,7 +10,7 @@
<div class="item context clipboard" data-clipboard-text="{{Printf "%s%s/issues/%d#%s" AppUrl .ctx.Repository.FullName .ctx.Issue.Index .item.HashTag}}">{{.ctx.i18n.Tr "repo.issues.context.copy_link"}}</div>
{{end}}
<div class="item context quote-reply {{if .diff}}quote-reply-diff{{end}}" data-target="{{.item.ID}}">{{.ctx.i18n.Tr "repo.issues.context.quote_reply"}}</div>
{{if or .ctx.Permission.IsAdmin .ctx.IsIssuePoster .ctx.HasIssuesOrPullsWritePermission}}
{{if or .ctx.Permission.IsAdmin .IsCommentPoster .ctx.HasIssuesOrPullsWritePermission}}
<div class="divider"></div>
<div class="item context edit-content">{{.ctx.i18n.Tr "repo.issues.context.edit"}}</div>
{{if .delete}}

View File

@@ -75,7 +75,7 @@
{{- else}}red{{end}}">{{svg "octicon-git-merge" 32}}</a>
<div class="content">
{{template "repo/pulls/status" .}}
<div class="ui {{if not $.LatestCommitStatus}}top attached header{{else}}attached merge-section segment{{end}}">
<div class="ui attached merge-section segment {{if not $.LatestCommitStatus}}no-header{{end}}">
{{if .Issue.PullRequest.HasMerged}}
<div class="item text purple">
{{if .Issue.PullRequest.MergedCommitID}}

View File

@@ -357,7 +357,7 @@
{{if ne .Issue.DeadlineUnix 0}}
<p>
{{svg "octicon-calendar" 16}}
{{.Issue.DeadlineUnix.FormatShort}}
{{.Issue.DeadlineUnix.FormatDate}}
{{if .Issue.IsOverdue}}
<span style="color: red;">{{.i18n.Tr "repo.issues.due_date_overdue"}}</span>
{{end}}

View File

@@ -21,7 +21,7 @@
<a class="item" data-tab="preview">{{.i18n.Tr "preview"}}</a>
</div>
<div class="field">
<textarea class="js-quick-submit" id="edit_area" name="content" data-id="wiki-{{.title}}" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}/wiki" required>{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea>
<textarea class="js-quick-submit" id="edit_area" name="content" data-id="wiki-{{.title}}" data-url="{{.Repository.APIURL}}/markdown" data-context="{{.RepoLink}}" required>{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea>
</div>
<div class="field">
<input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}">

View File

@@ -1771,8 +1771,8 @@
},
{
"type": "boolean",
"description": "only include private repositories this user has access to (defaults to false)",
"name": "onlyPrivate",
"description": "show only pubic, private or all repositories (defaults to all)",
"name": "is_private",
"in": "query"
},
{
@@ -2746,6 +2746,15 @@
"responses": {
"200": {
"$ref": "#/responses/FileResponse"
},
"403": {
"$ref": "#/responses/error"
},
"404": {
"$ref": "#/responses/notFound"
},
"422": {
"$ref": "#/responses/error"
}
}
},
@@ -2795,6 +2804,15 @@
"responses": {
"201": {
"$ref": "#/responses/FileResponse"
},
"403": {
"$ref": "#/responses/error"
},
"404": {
"$ref": "#/responses/notFound"
},
"422": {
"$ref": "#/responses/error"
}
}
},
@@ -6575,6 +6593,9 @@
"403": {
"$ref": "#/responses/forbidden"
},
"409": {
"$ref": "#/responses/error"
},
"412": {
"$ref": "#/responses/error"
},
@@ -9105,6 +9126,9 @@
"201": {
"$ref": "#/responses/GPGKey"
},
"404": {
"$ref": "#/responses/notFound"
},
"422": {
"$ref": "#/responses/validationError"
}
@@ -9165,6 +9189,9 @@
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
}
}
@@ -11953,6 +11980,10 @@
},
"x-go-name": "Assignees"
},
"base": {
"type": "string",
"x-go-name": "Base"
},
"body": {
"type": "string",
"x-go-name": "Body"

View File

@@ -101,7 +101,7 @@
</div>
<div class="ui attached table segment">
<ul class="repo-owner-name-list">
<li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo)">
<li v-for="repo in repos" :class="{'private': repo.private}">
<a :href="suburl + '/' + repo.full_name">
<svg :class="'svg ' + repoClass(repo)" width="16" height="16" aria-hidden="true"><use :xlink:href="'#' + repoClass(repo)" /></svg>
<strong class="text truncate item-name">${repo.full_name}</strong>

View File

@@ -1,26 +1,26 @@
# go-enry [![GoDoc](https://godoc.org/github.com/go-enry/go-enry?status.svg)](https://pkg.go.dev/github.com/go-enry/go-enry/v2) [![Test](https://github.com/go-enry/go-enry/workflows/Test/badge.svg)](https://github.com/go-enry/go-enry/actions?query=workflow%3ATest+branch%3Amaster) [![codecov](https://codecov.io/gh/go-enry/go-enry/branch/master/graph/badge.svg)](https://codecov.io/gh/go-enry/go-enry)
Programming language detector and toolbox to ignore binary or vendored files. *enry*, started as a port to _Go_ of the original [Linguist](https://github.com/github/linguist) _Ruby_ library, that has an improved *2x performance*.
Programming language detector and toolbox to ignore binary or vendored files. _enry_, started as a port to _Go_ of the original [Linguist](https://github.com/github/linguist) _Ruby_ library, that has an improved _2x performance_.
* [CLI](#cli)
* [Library](#library)
* [Use cases](#use-cases)
* [By filename](#by-filename)
* [By text](#by-text)
* [By file](#by-file)
* [Filtering](#filtering-vendoring-binaries-etc)
* [Coloring](#language-colors-and-groups)
* [Languages](#languages)
* [Go](#go)
* [Java bindings](#java-bindings)
* [Python bindings](#python-bindings)
* [Divergences from linguist](#divergences-from-linguist)
* [Benchmarks](#benchmarks)
* [Why Enry?](#why-enry)
* [Development](#development)
* [Sync with github/linguist upstream](#sync-with-githublinguist-upstream)
* [Misc](#misc)
* [License](#license)
- [CLI](#cli)
- [Library](#library)
- [Use cases](#use-cases)
- [By filename](#by-filename)
- [By text](#by-text)
- [By file](#by-file)
- [Filtering](#filtering-vendoring-binaries-etc)
- [Coloring](#language-colors-and-groups)
- [Languages](#languages)
- [Go](#go)
- [Java bindings](#java-bindings)
- [Python bindings](#python-bindings)
- [Divergences from linguist](#divergences-from-linguist)
- [Benchmarks](#benchmarks)
- [Why Enry?](#why-enry)
- [Development](#development)
- [Sync with github/linguist upstream](#sync-with-githublinguist-upstream)
- [Misc](#misc)
- [License](#license)
# CLI
@@ -28,50 +28,62 @@ The CLI binary is hosted in a separate repository [go-enry/enry](https://github.
# Library
*enry* is also a Go library for guessing a programming language that exposes API through FFI to multiple programming environments.
_enry_ is also a Go library for guessing a programming language that exposes API through FFI to multiple programming environments.
## Use cases
*enry* guesses a programming language using a sequence of matching *strategies* that are
applied progressively to narrow down the possible options. Each *strategy* varies on the type
_enry_ guesses a programming language using a sequence of matching _strategies_ that are
applied progressively to narrow down the possible options. Each _strategy_ varies on the type
of input data that it needs to make a decision: file name, extension, the first line of the file, the full content of the file, etc.
Depending on available input data, enry API can be roughly divided into the next categories or use cases.
### By filename
Next functions require only a name of the file to make a guess:
- `GetLanguageByExtension` uses only file extension (wich may be ambiguous)
- `GetLanguageByFilename` useful for cases like `.gitignore`, `.bashrc`, etc
- all [filtering helpers](#filtering)
Please note that such guesses are expected not to be very accurate.
Next functions require only a name of the file to make a guess:
- `GetLanguageByExtension` uses only file extension (wich may be ambiguous)
- `GetLanguageByFilename` useful for cases like `.gitignore`, `.bashrc`, etc
- all [filtering helpers](#filtering)
Please note that such guesses are expected not to be very accurate.
### By text
To make a guess only based on the content of the file or a text snippet, use
- `GetLanguageByShebang` reads only the first line of text to identify the [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)).
- `GetLanguageByModeline` for cases when Vim/Emacs modeline e.g. `/* vim: set ft=cpp: */` may be present at a head or a tail of the text.
- `GetLanguageByClassifier` uses a Bayesian classifier trained on all the `./samples/` from Linguist.
It usually is a last-resort strategy that is used to disambiguate the guess of the previous strategies, and thus it requires a list of "candidate" guesses. One can provide a list of all known languages - keys from the `data.LanguagesLogProbabilities` as possible candidates if more intelligent hypotheses are not available, at the price of possibly suboptimal accuracy.
To make a guess only based on the content of the file or a text snippet, use
- `GetLanguageByShebang` reads only the first line of text to identify the [shebang](<https://en.wikipedia.org/wiki/Shebang_(Unix)>).
- `GetLanguageByModeline` for cases when Vim/Emacs modeline e.g. `/* vim: set ft=cpp: */` may be present at a head or a tail of the text.
- `GetLanguageByClassifier` uses a Bayesian classifier trained on all the `./samples/` from Linguist.
It usually is a last-resort strategy that is used to disambiguate the guess of the previous strategies, and thus it requires a list of "candidate" guesses. One can provide a list of all known languages - keys from the `data.LanguagesLogProbabilities` as possible candidates if more intelligent hypotheses are not available, at the price of possibly suboptimal accuracy.
### By file
The most accurate guess would be one when both, the file name and the content are available:
- `GetLanguagesByContent` only uses file extension and a set of regexp-based content heuristics.
- `GetLanguages` uses the full set of matching strategies and is expected to be most accurate.
- `GetLanguagesByContent` only uses file extension and a set of regexp-based content heuristics.
- `GetLanguages` uses the full set of matching strategies and is expected to be most accurate.
### Filtering: vendoring, binaries, etc
*enry* expose a set of file-level helpers `Is*` to simplify filtering out the files that are less interesting for the purpose of source code analysis:
- `IsBinary`
- `IsVendor`
- `IsConfiguration`
- `IsDocumentation`
- `IsDotFile`
- `IsImage`
_enry_ expose a set of file-level helpers `Is*` to simplify filtering out the files that are less interesting for the purpose of source code analysis:
- `IsBinary`
- `IsVendor`
- `IsConfiguration`
- `IsDocumentation`
- `IsDotFile`
- `IsImage`
- `IsTest`
- `IsGenerated`
### Language colors and groups
*enry* exposes function to get language color to use for example in presenting statistics in graphs:
- `GetColor`
- `GetLanguageGroup` can be used to group similar languages together e.g. for `Less` this function will return `CSS`
_enry_ exposes function to get language color to use for example in presenting statistics in graphs:
- `GetColor`
- `GetLanguageGroup` can be used to group similar languages together e.g. for `Less` this function will return `CSS`
## Languages
@@ -136,39 +148,36 @@ Generated Python bindings using a C shared library and cffi are WIP under [src-d
A library is going to be published on pypi as [enry](https://pypi.org/project/enry/) for
macOS and linux platforms. Windows support is planned under [src-d/enry#150](https://github.com/src-d/enry/issues/150).
Divergences from Linguist
------------
## Divergences from Linguist
The `enry` library is based on the data from `github/linguist` version **v7.9.0**.
Parsing [linguist/samples](https://github.com/github/linguist/tree/master/samples) the following `enry` results are different from the Linguist:
* [Heuristics for ".es" extension](https://github.com/github/linguist/blob/e761f9b013e5b61161481fcb898b59721ee40e3d/lib/linguist/heuristics.yml#L103) in JavaScript could not be parsed, due to unsupported backreference in RE2 regexp engine.
- [Heuristics for ".es" extension](https://github.com/github/linguist/blob/e761f9b013e5b61161481fcb898b59721ee40e3d/lib/linguist/heuristics.yml#L103) in JavaScript could not be parsed, due to unsupported backreference in RE2 regexp engine.
* [Heuristics for ".rno" extension](https://github.com/github/linguist/blob/3a1bd3c3d3e741a8aaec4704f782e06f5cd2a00d/lib/linguist/heuristics.yml#L365) in RUNOFF could not be parsed, due to unsupported lookahead in RE2 regexp engine.
- [Heuristics for ".rno" extension](https://github.com/github/linguist/blob/3a1bd3c3d3e741a8aaec4704f782e06f5cd2a00d/lib/linguist/heuristics.yml#L365) in RUNOFF could not be parsed, due to unsupported lookahead in RE2 regexp engine.
* [Heuristics for ".inc" extension](https://github.com/github/linguist/blob/f0e2d0d7f1ce600b2a5acccaef6b149c87d8b99c/lib/linguist/heuristics.yml#L222) in NASL could not be parsed, due to unsupported possessive quantifier in RE2 regexp engine.
- [Heuristics for ".inc" extension](https://github.com/github/linguist/blob/f0e2d0d7f1ce600b2a5acccaef6b149c87d8b99c/lib/linguist/heuristics.yml#L222) in NASL could not be parsed, due to unsupported possessive quantifier in RE2 regexp engine.
* As of [Linguist v5.3.2](https://github.com/github/linguist/releases/tag/v5.3.2) it is using [flex-based scanner in C for tokenization](https://github.com/github/linguist/pull/3846). Enry still uses [extract_token](https://github.com/github/linguist/pull/3846/files#diff-d5179df0b71620e3fac4535cd1368d15L60) regex-based algorithm. See [#193](https://github.com/src-d/enry/issues/193).
- As of [Linguist v5.3.2](https://github.com/github/linguist/releases/tag/v5.3.2) it is using [flex-based scanner in C for tokenization](https://github.com/github/linguist/pull/3846). Enry still uses [extract_token](https://github.com/github/linguist/pull/3846/files#diff-d5179df0b71620e3fac4535cd1368d15L60) regex-based algorithm. See [#193](https://github.com/src-d/enry/issues/193).
* Bayesian classifier can't distinguish "SQL" from "PLpgSQL. See [#194](https://github.com/src-d/enry/issues/194).
- Bayesian classifier can't distinguish "SQL" from "PLpgSQL. See [#194](https://github.com/src-d/enry/issues/194).
* Detection of [generated files](https://github.com/github/linguist/blob/bf95666fc15e49d556f2def4d0a85338423c25f3/lib/linguist/generated.rb#L53) is not supported yet.
(Thus they are not excluded from CLI output). See [#213](https://github.com/src-d/enry/issues/213).
- Detection of [generated files](https://github.com/github/linguist/blob/bf95666fc15e49d556f2def4d0a85338423c25f3/lib/linguist/generated.rb#L53) is not supported yet.
(Thus they are not excluded from CLI output). See [#213](https://github.com/src-d/enry/issues/213).
* XML detection strategy is not implemented. See [#192](https://github.com/src-d/enry/issues/192).
- XML detection strategy is not implemented. See [#192](https://github.com/src-d/enry/issues/192).
* Overriding languages and types though `.gitattributes` is not yet supported. See [#18](https://github.com/src-d/enry/issues/18).
- Overriding languages and types though `.gitattributes` is not yet supported. See [#18](https://github.com/src-d/enry/issues/18).
* `enry` CLI output does NOT exclude `.gitignore`ed files and git submodules, as Linguist does
- `enry` CLI output does NOT exclude `.gitignore`ed files and git submodules, as Linguist does
In all the cases above that have an issue number - we plan to update enry to match Linguist behavior.
## Benchmarks
Benchmarks
------------
Enry's language detection has been compared with Linguist's on [*linguist/samples*](https://github.com/github/linguist/tree/master/samples).
Enry's language detection has been compared with Linguist's on [_linguist/samples_](https://github.com/github/linguist/tree/master/samples).
We got these results:
@@ -182,9 +191,7 @@ Go regexp engine being slower than Ruby's on, wich is based on [oniguruma](https
See [instructions](#misc) for running enry with oniguruma.
Why Enry?
------------
## Why Enry?
In the movie [My Fair Lady](https://en.wikipedia.org/wiki/My_Fair_Lady), [Professor Henry Higgins](http://www.imdb.com/character/ch0011719/) is a linguist who at the very beginning of the movie enjoys guessing the origin of people based on their accent.
@@ -199,10 +206,9 @@ To run the tests use:
Setting `ENRY_TEST_REPO` to the path to existing checkout of Linguist will avoid cloning it and sepeed tests up.
Setting `ENRY_DEBUG=1` will provide insight in the Bayesian classifier building done by `make code-generate`.
### Sync with github/linguist upstream
*enry* re-uses parts of the original [github/linguist](https://github.com/github/linguist) to generate internal data structures.
_enry_ re-uses parts of the original [github/linguist](https://github.com/github/linguist) to generate internal data structures.
In order to update to the latest release of linguist do:
```bash
@@ -217,10 +223,10 @@ $ make code-generate
To stay in sync, enry needs to be updated when a new release of the linguist includes changes to any of the following files:
* [languages.yml](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml)
* [heuristics.yml](https://github.com/github/linguist/blob/master/lib/linguist/heuristics.yml)
* [vendor.yml](https://github.com/github/linguist/blob/master/lib/linguist/vendor.yml)
* [documentation.yml](https://github.com/github/linguist/blob/master/lib/linguist/documentation.yml)
- [languages.yml](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml)
- [heuristics.yml](https://github.com/github/linguist/blob/master/lib/linguist/heuristics.yml)
- [vendor.yml](https://github.com/github/linguist/blob/master/lib/linguist/vendor.yml)
- [documentation.yml](https://github.com/github/linguist/blob/master/lib/linguist/documentation.yml)
There is no automation for detecting the changes in the linguist project, so this process above has to be done manually from time to time.
@@ -229,8 +235,6 @@ the generated files (in [data](https://github.com/go-enry/go-enry/blob/master/da
Separating all the necessary "manual" code changes to a different PR that includes some background description and an update to the documentation on ["divergences from linguist"](#divergences-from-linguist) is very much appreciated as it simplifies the maintenance (review/release notes/etc).
## Misc
<details>
@@ -238,19 +242,20 @@ Separating all the necessary "manual" code changes to a different PR that includ
### Benchmark
All benchmark scripts are in [*benchmarks*](https://github.com/go-enry/go-enry/blob/master/benchmarks) directory.
All benchmark scripts are in [_benchmarks_](https://github.com/go-enry/go-enry/blob/master/benchmarks) directory.
#### Dependencies
As benchmarks depend on Ruby and Github-Linguist gem make sure you have:
- Ruby (e.g using [`rbenv`](https://github.com/rbenv/rbenv)), [`bundler`](https://bundler.io/) installed
- Docker
- [native dependencies](https://github.com/github/linguist/#dependencies) installed
- Build the gem `cd .linguist && bundle install && rake build_gem && cd -`
- Install it `gem install --no-rdoc --no-ri --local .linguist/github-linguist-*.gem`
As benchmarks depend on Ruby and Github-Linguist gem make sure you have:
- Ruby (e.g using [`rbenv`](https://github.com/rbenv/rbenv)), [`bundler`](https://bundler.io/) installed
- Docker
- [native dependencies](https://github.com/github/linguist/#dependencies) installed
- Build the gem `cd .linguist && bundle install && rake build_gem && cd -`
- Install it `gem install --no-rdoc --no-ri --local .linguist/github-linguist-*.gem`
#### Quick benchmark
To run quicker benchmarks
make benchmarks
@@ -259,19 +264,20 @@ to get average times for the primary detection function and strategies for the w
make benchmarks-samples
#### Full benchmark
If you want to reproduce the same benchmarks as reported above:
- Make sure all [dependencies](#benchmark-dependencies) are installed
- Install [gnuplot](http://gnuplot.info) (in order to plot the histogram)
- Run `ENRY_TEST_REPO="$PWD/.linguist" benchmarks/run.sh` (takes ~15h)
- Make sure all [dependencies](#benchmark-dependencies) are installed
- Install [gnuplot](http://gnuplot.info) (in order to plot the histogram)
- Run `ENRY_TEST_REPO="$PWD/.linguist" benchmarks/run.sh` (takes ~15h)
It will run the benchmarks for enry and Linguist, parse the output, create csv files and plot the histogram.
### Faster regexp engine (optional)
[Oniguruma](https://github.com/kkos/oniguruma) is CRuby's regular expression engine.
It is very fast and performs better than the one built into Go runtime. *enry* supports swapping
It is very fast and performs better than the one built into Go runtime. _enry_ supports swapping
between those two engines thanks to [rubex](https://github.com/moovweb/rubex) project.
The typical overall speedup from using Oniguruma is 1.5-2x. However, it requires CGo and the external shared library.
On macOS with [Homebrew](https://brew.sh/), it is:
@@ -296,8 +302,6 @@ and then rebuild the project.
</details>
License
------------
## License
Apache License, Version 2.0. See [LICENSE](LICENSE)

View File

@@ -328,15 +328,13 @@ func getInterpreter(data []byte) (interpreter string) {
return
}
func getFirstLine(data []byte) []byte {
buf := bufio.NewScanner(bytes.NewReader(data))
buf.Scan()
line := buf.Bytes()
if err := buf.Err(); err != nil {
return nil
func getFirstLine(content []byte) []byte {
nlpos := bytes.IndexByte(content, '\n')
if nlpos < 0 {
return content
}
return line
return content[:nlpos]
}
func hasShebang(line []byte) bool {

View File

@@ -3,24 +3,24 @@
package data
import "gopkg.in/toqueteos/substring.v1"
import "github.com/go-enry/go-enry/v2/regex"
var DocumentationMatchers = substring.Or(
substring.Regexp(`^[Dd]ocs?/`),
substring.Regexp(`(^|/)[Dd]ocumentation/`),
substring.Regexp(`(^|/)[Gg]roovydoc/`),
substring.Regexp(`(^|/)[Jj]avadoc/`),
substring.Regexp(`^[Mm]an/`),
substring.Regexp(`^[Ee]xamples/`),
substring.Regexp(`^[Dd]emos?/`),
substring.Regexp(`(^|/)inst/doc/`),
substring.Regexp(`(^|/)CHANGE(S|LOG)?(\.|$)`),
substring.Regexp(`(^|/)CONTRIBUTING(\.|$)`),
substring.Regexp(`(^|/)COPYING(\.|$)`),
substring.Regexp(`(^|/)INSTALL(\.|$)`),
substring.Regexp(`(^|/)LICEN[CS]E(\.|$)`),
substring.Regexp(`(^|/)[Ll]icen[cs]e(\.|$)`),
substring.Regexp(`(^|/)README(\.|$)`),
substring.Regexp(`(^|/)[Rr]eadme(\.|$)`),
substring.Regexp(`^[Ss]amples?/`),
)
var DocumentationMatchers = []regex.EnryRegexp{
regex.MustCompile(`^[Dd]ocs?/`),
regex.MustCompile(`(^|/)[Dd]ocumentation/`),
regex.MustCompile(`(^|/)[Gg]roovydoc/`),
regex.MustCompile(`(^|/)[Jj]avadoc/`),
regex.MustCompile(`^[Mm]an/`),
regex.MustCompile(`^[Ee]xamples/`),
regex.MustCompile(`^[Dd]emos?/`),
regex.MustCompile(`(^|/)inst/doc/`),
regex.MustCompile(`(^|/)CHANGE(S|LOG)?(\.|$)`),
regex.MustCompile(`(^|/)CONTRIBUTING(\.|$)`),
regex.MustCompile(`(^|/)COPYING(\.|$)`),
regex.MustCompile(`(^|/)INSTALL(\.|$)`),
regex.MustCompile(`(^|/)LICEN[CS]E(\.|$)`),
regex.MustCompile(`(^|/)[Ll]icen[cs]e(\.|$)`),
regex.MustCompile(`(^|/)README(\.|$)`),
regex.MustCompile(`(^|/)[Rr]eadme(\.|$)`),
regex.MustCompile(`^[Ss]amples?/`),
}

823
vendor/github.com/go-enry/go-enry/v2/data/generated.go generated vendored Normal file
View File

@@ -0,0 +1,823 @@
package data
import (
"bytes"
"strings"
"github.com/go-enry/go-enry/v2/regex"
)
// GeneratedCodeExtensions contains all extensions that belong to generated
// files for sure.
var GeneratedCodeExtensions = map[string]struct{}{
// XCode files
".nib": {},
".xcworkspacedata": {},
".xcuserstate": {},
}
// GeneratedCodeNameMatcher is a function that tells whether the file with the
// given name is generated.
type GeneratedCodeNameMatcher func(string) bool
func nameMatches(pattern string) GeneratedCodeNameMatcher {
r := regex.MustCompile(pattern)
return func(name string) bool {
return r.MatchString(name)
}
}
func nameContains(pattern string) GeneratedCodeNameMatcher {
return func(name string) bool {
return strings.Contains(name, pattern)
}
}
func nameEndsWith(pattern string) GeneratedCodeNameMatcher {
return func(name string) bool {
return strings.HasSuffix(name, pattern)
}
}
// GeneratedCodeNameMatchers are all the matchers that check whether the code
// is generated based only on the file name.
var GeneratedCodeNameMatchers = []GeneratedCodeNameMatcher{
// Cocoa pods
nameMatches(`(^Pods|\/Pods)\/`),
// Carthage build
nameMatches(`(^|\/)Carthage\/Build\/`),
// NET designer file
nameMatches(`(?i)\.designer\.(cs|vb)$`),
// Generated NET specflow feature file
nameEndsWith(".feature.cs"),
// Node modules
nameContains("node_modules/"),
// Go vendor
nameMatches(`vendor\/([-0-9A-Za-z]+\.)+(com|edu|gov|in|me|net|org|fm|io)`),
// Go lock
nameEndsWith("Gopkg.lock"),
nameEndsWith("glide.lock"),
// Esy lock
nameMatches(`(^|\/)(\w+\.)?esy.lock$`),
// NPM shrinkwrap
nameEndsWith("npm-shrinkwrap.json"),
// NPM package lock
nameEndsWith("package-lock.json"),
// Yarn plugnplay
nameMatches(`(^|\/)\.pnp\.(c|m)?js$`),
// Godeps
nameContains("Godeps/"),
// Composer lock
nameEndsWith("composer.lock"),
// Generated by zephir
nameMatches(`.\.zep\.(?:c|h|php)$`),
// Cargo lock
nameEndsWith("Cargo.lock"),
// Pipenv lock
nameEndsWith("Pipfile.lock"),
// GraphQL relay
nameContains("__generated__/"),
}
// GeneratedCodeMatcher checks whether the file with the given data is
// generated code.
type GeneratedCodeMatcher func(path, ext string, content []byte) bool
// GeneratedCodeMatchers is the list of all generated code matchers that
// rely on checking the content of the file to make the guess.
var GeneratedCodeMatchers = []GeneratedCodeMatcher{
isMinifiedFile,
hasSourceMapReference,
isSourceMap,
isCompiledCoffeeScript,
isGeneratedNetDocfile,
isGeneratedJavaScriptPEGParser,
isGeneratedPostScript,
isGeneratedGo,
isGeneratedProtobuf,
isGeneratedJavaScriptProtocolBuffer,
isGeneratedApacheThrift,
isGeneratedJNIHeader,
isVCRCassette,
isCompiledCythonFile,
isGeneratedModule,
isGeneratedUnity3DMeta,
isGeneratedRacc,
isGeneratedJFlex,
isGeneratedGrammarKit,
isGeneratedRoxygen2,
isGeneratedJison,
isGeneratedGRPCCpp,
isGeneratedDart,
isGeneratedPerlPPPortHeader,
isGeneratedGameMakerStudio,
isGeneratedGimp,
isGeneratedVisualStudio6,
isGeneratedHaxe,
isGeneratedHTML,
isGeneratedJooq,
}
func canBeMinified(ext string) bool {
return ext == ".js" || ext == ".css"
}
// isMinifiedFile returns whether the file may be minified.
// We consider a minified file any css or js file whose average number of chars
// per line is more than 110.
func isMinifiedFile(path, ext string, content []byte) bool {
if !canBeMinified(ext) {
return false
}
var chars, lines uint64
forEachLine(content, func(line []byte) {
chars += uint64(len(line))
lines++
})
if lines == 0 {
return false
}
return chars/lines > 110
}
var sourceMapRegex = regex.MustCompile(`^\/[*\/][\#@] source(?:Mapping)?URL|sourceURL=`)
// hasSourceMapReference returns whether the file contains a reference to a
// source-map file.
func hasSourceMapReference(_ string, ext string, content []byte) bool {
if !canBeMinified(ext) {
return false
}
for _, line := range getLines(content, -2) {
if sourceMapRegex.Match(line) {
return true
}
}
return false
}
var sourceMapRegexps = []regex.EnryRegexp{
regex.MustCompile(`^{"version":\d+,`),
regex.MustCompile(`^\/\*\* Begin line maps\. \*\*\/{`),
}
// isSourceMap returns whether the file itself is a source map.
func isSourceMap(path, _ string, content []byte) bool {
if strings.HasSuffix(path, ".js.map") || strings.HasSuffix(path, ".css.map") {
return true
}
firstLine := getFirstLine(content)
if len(firstLine) == 0 {
return false
}
for _, r := range sourceMapRegexps {
if r.Match(firstLine) {
return true
}
}
return false
}
func isCompiledCoffeeScript(path, ext string, content []byte) bool {
if ext != ".js" {
return false
}
firstLine := getFirstLine(content)
lastLines := getLines(content, -2)
if len(lastLines) < 2 {
return false
}
if string(firstLine) == "(function() {" &&
string(lastLines[1]) == "}).call(this);" &&
string(lastLines[0]) == "" {
score := 0
forEachLine(content, func(line []byte) {
if bytes.Contains(line, []byte("var ")) {
// Underscored temp vars are likely to be Coffee
score += 1 * countAppearancesInLine(line, "_fn", "_i", "_len", "_ref", "_results")
// bind and extend functions are very Coffee specific
score += 3 * countAppearancesInLine(line, "__bind", "__extends", "__hasProp", "__indexOf", "__slice")
}
})
// Require a score of 3. This is fairly abritrary. Consider tweaking later.
// See: https://github.com/github/linguist/blob/master/lib/linguist/generated.rb#L176-L213
return score >= 3
}
return false
}
func isGeneratedNetDocfile(_, ext string, content []byte) bool {
if ext != ".xml" {
return false
}
lines := bytes.Split(content, []byte{'\n'})
if len(lines) <= 3 {
return false
}
return bytes.Contains(lines[1], []byte("<doc>")) &&
bytes.Contains(lines[2], []byte("<assembly>")) &&
bytes.Contains(lines[len(lines)-2], []byte("</doc>"))
}
var pegJavaScriptGeneratedRegex = regex.MustCompile(`^(?:[^\/]|\/[^\*])*\/\*(?:[^\*]|\*[^\/])*Generated by PEG.js`)
func isGeneratedJavaScriptPEGParser(_, ext string, content []byte) bool {
if ext != ".js" {
return false
}
// PEG.js-generated parsers include a comment near the top of the file
// that marks them as such.
return pegJavaScriptGeneratedRegex.Match(bytes.Join(getLines(content, 5), []byte("")))
}
var postScriptType1And42Regex = regex.MustCompile(`(\n|\r\n|\r)\s*(?:currentfile eexec\s+|\/sfnts\s+\[)`)
var postScriptRegexes = []regex.EnryRegexp{
regex.MustCompile(`[0-9]|draw|mpage|ImageMagick|inkscape|MATLAB`),
regex.MustCompile(`PCBNEW|pnmtops|\(Unknown\)|Serif Affinity|Filterimage -tops`),
}
func isGeneratedPostScript(_, ext string, content []byte) bool {
if ext != ".ps" && ext != ".eps" && ext != ".pfa" {
return false
}
// Type 1 and Type 42 fonts converted to PostScript are stored as hex-encoded byte streams; these
// streams are always preceded the `eexec` operator (if Type 1), or the `/sfnts` key (if Type 42).
if postScriptType1And42Regex.Match(content) {
return true
}
// We analyze the "%%Creator:" comment, which contains the author/generator
// of the file. If there is one, it should be in one of the first few lines.
var creator []byte
for _, line := range getLines(content, 10) {
if bytes.HasPrefix(line, []byte("%%Creator: ")) {
creator = line
break
}
}
if len(creator) == 0 {
return false
}
// EAGLE doesn't include a version number when it generates PostScript.
// However, it does prepend its name to the document's "%%Title" field.
if bytes.Contains(creator, []byte("EAGLE")) {
for _, line := range getLines(content, 5) {
if bytes.HasPrefix(line, []byte("%%Title: EAGLE Drawing ")) {
return true
}
}
}
// Most generators write their version number, while human authors' or companies'
// names don't contain numbers. So look if the line contains digits. Also
// look for some special cases without version numbers.
for _, r := range postScriptRegexes {
if r.Match(creator) {
return true
}
}
return false
}
func isGeneratedGo(_, ext string, content []byte) bool {
if ext != ".go" {
return false
}
lines := getLines(content, 40)
if len(lines) <= 1 {
return false
}
for _, line := range lines {
if bytes.Contains(line, []byte("Code generated by")) {
return true
}
}
return false
}
var protoExtensions = map[string]struct{}{
".py": {},
".java": {},
".h": {},
".cc": {},
".cpp": {},
".m": {},
".rb": {},
".php": {},
}
func isGeneratedProtobuf(_, ext string, content []byte) bool {
if _, ok := protoExtensions[ext]; !ok {
return false
}
lines := getLines(content, 3)
if len(lines) <= 1 {
return false
}
for _, line := range lines {
if bytes.Contains(line, []byte("Generated by the protocol buffer compiler. DO NOT EDIT!")) {
return true
}
}
return false
}
func isGeneratedJavaScriptProtocolBuffer(_, ext string, content []byte) bool {
if ext != ".js" {
return false
}
lines := getLines(content, 6)
if len(lines) < 6 {
return false
}
return bytes.Contains(lines[5], []byte("GENERATED CODE -- DO NOT EDIT!"))
}
var apacheThriftExtensions = map[string]struct{}{
".rb": {},
".py": {},
".go": {},
".js": {},
".m": {},
".java": {},
".h": {},
".cc": {},
".cpp": {},
".php": {},
}
func isGeneratedApacheThrift(_, ext string, content []byte) bool {
if _, ok := apacheThriftExtensions[ext]; !ok {
return false
}
for _, line := range getLines(content, 6) {
if bytes.Contains(line, []byte("Autogenerated by Thrift Compiler")) {
return true
}
}
return false
}
func isGeneratedJNIHeader(_, ext string, content []byte) bool {
if ext != ".h" {
return false
}
lines := getLines(content, 2)
if len(lines) < 2 {
return false
}
return bytes.Contains(lines[0], []byte("/* DO NOT EDIT THIS FILE - it is machine generated */")) &&
bytes.Contains(lines[1], []byte("#include <jni.h>"))
}
func isVCRCassette(_, ext string, content []byte) bool {
if ext != ".yml" {
return false
}
lines := getLines(content, -2)
if len(lines) < 2 {
return false
}
return bytes.Contains(lines[1], []byte("recorded_with: VCR"))
}
func isCompiledCythonFile(_, ext string, content []byte) bool {
if ext != ".c" && ext != ".cpp" {
return false
}
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
return bytes.Contains(lines[0], []byte("Generated by Cython"))
}
func isGeneratedModule(_, ext string, content []byte) bool {
if ext != ".mod" {
return false
}
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
return bytes.Contains(lines[0], []byte("PCBNEW-LibModule-V")) ||
bytes.Contains(lines[0], []byte("GFORTRAN module version '"))
}
func isGeneratedUnity3DMeta(_, ext string, content []byte) bool {
if ext != ".meta" {
return false
}
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
return bytes.Contains(lines[0], []byte("fileFormatVersion: "))
}
func isGeneratedRacc(_, ext string, content []byte) bool {
if ext != ".rb" {
return false
}
lines := getLines(content, 3)
if len(lines) < 3 {
return false
}
return bytes.HasPrefix(lines[2], []byte("# This file is automatically generated by Racc"))
}
func isGeneratedJFlex(_, ext string, content []byte) bool {
if ext != ".java" {
return false
}
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
return bytes.HasPrefix(lines[0], []byte("/* The following code was generated by JFlex "))
}
func isGeneratedGrammarKit(_, ext string, content []byte) bool {
if ext != ".java" {
return false
}
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
return bytes.Contains(lines[0], []byte("// This is a generated file. Not intended for manual editing."))
}
func isGeneratedRoxygen2(_, ext string, content []byte) bool {
if ext != ".rd" {
return false
}
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
return bytes.Contains(lines[0], []byte("% Generated by roxygen2: do not edit by hand"))
}
func isGeneratedJison(_, ext string, content []byte) bool {
if ext != ".js" {
return false
}
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
return bytes.Contains(lines[0], []byte("/* parser generated by jison ")) ||
bytes.Contains(lines[0], []byte("/* generated by jison-lex "))
}
func isGeneratedGRPCCpp(_, ext string, content []byte) bool {
switch ext {
case ".cpp", ".hpp", ".h", ".cc":
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
return bytes.Contains(lines[0], []byte("// Generated by the gRPC"))
default:
return false
}
}
var dartRegex = regex.MustCompile(`generated code\W{2,3}do not modify`)
func isGeneratedDart(_, ext string, content []byte) bool {
if ext != ".dart" {
return false
}
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
return dartRegex.Match(bytes.ToLower(lines[0]))
}
func isGeneratedPerlPPPortHeader(name, _ string, content []byte) bool {
if !strings.HasSuffix(name, "ppport.h") {
return false
}
lines := getLines(content, 10)
if len(lines) < 10 {
return false
}
return bytes.Contains(lines[8], []byte("Automatically created by Devel::PPPort"))
}
var (
gameMakerStudioFirstLineRegex = regex.MustCompile(`^\d\.\d\.\d.+\|\{`)
gameMakerStudioThirdLineRegex = regex.MustCompile(`\"modelName\"\:\s*\"GM`)
)
func isGeneratedGameMakerStudio(_, ext string, content []byte) bool {
if ext != ".yy" && ext != ".yyp" {
return false
}
lines := getLines(content, 3)
if len(lines) < 3 {
return false
}
return gameMakerStudioThirdLineRegex.Match(lines[2]) ||
gameMakerStudioFirstLineRegex.Match(lines[0])
}
var gimpRegexes = []regex.EnryRegexp{
regex.MustCompile(`\/\* GIMP [a-zA-Z0-9\- ]+ C\-Source image dump \(.+?\.c\) \*\/`),
regex.MustCompile(`\/\* GIMP header image file format \([a-zA-Z0-9\- ]+\)\: .+?\.h \*\/`),
}
func isGeneratedGimp(_, ext string, content []byte) bool {
if ext != ".c" && ext != ".h" {
return false
}
lines := getLines(content, 1)
if len(lines) < 1 {
return false
}
for _, r := range gimpRegexes {
if r.Match(lines[0]) {
return true
}
}
return false
}
func isGeneratedVisualStudio6(_, ext string, content []byte) bool {
if ext != ".dsp" {
return false
}
for _, l := range getLines(content, 3) {
if bytes.Contains(l, []byte("# Microsoft Developer Studio Generated Build File")) {
return true
}
}
return false
}
var haxeExtensions = map[string]struct{}{
".js": {},
".py": {},
".lua": {},
".cpp": {},
".h": {},
".java": {},
".cs": {},
".php": {},
}
func isGeneratedHaxe(_, ext string, content []byte) bool {
if _, ok := haxeExtensions[ext]; !ok {
return false
}
for _, l := range getLines(content, 3) {
if bytes.Contains(l, []byte("Generated by Haxe")) {
return true
}
}
return false
}
var (
doxygenRegex = regex.MustCompile(`<!--\s+Generated by Doxygen\s+[.0-9]+\s*-->`)
htmlMetaRegex = regex.MustCompile(`<meta(\s+[^>]+)>`)
htmlMetaContentRegex = regex.MustCompile(`\s+(name|content|value)\s*=\s*("[^"]+"|'[^']+'|[^\s"']+)`)
orgModeMetaRegex = regex.MustCompile(`org\s+mode`)
)
func isGeneratedHTML(_, ext string, content []byte) bool {
if ext != ".html" && ext != ".htm" && ext != ".xhtml" {
return false
}
lines := getLines(content, 30)
// Pkgdown
if len(lines) >= 2 {
for _, l := range lines[:2] {
if bytes.Contains(l, []byte("<!-- Generated by pkgdown: do not edit by hand -->")) {
return true
}
}
}
// Mandoc
if len(lines) > 2 &&
bytes.HasPrefix(lines[2], []byte("<!-- This is an automatically generated file.")) {
return true
}
// Doxygen
for _, l := range lines {
if doxygenRegex.Match(l) {
return true
}
}
// HTML tag: <meta name="generator" content="" />
part := bytes.ToLower(bytes.Join(lines, []byte{' '}))
part = bytes.ReplaceAll(part, []byte{'\n'}, []byte{})
part = bytes.ReplaceAll(part, []byte{'\r'}, []byte{})
matches := htmlMetaRegex.FindAll(part, -1)
if len(matches) == 0 {
return false
}
for _, m := range matches {
var name, value, content string
ms := htmlMetaContentRegex.FindAllStringSubmatch(string(m), -1)
for _, m := range ms {
switch m[1] {
case "name":
name = m[2]
case "value":
value = m[2]
case "content":
content = m[2]
}
}
var val = value
if val == "" {
val = content
}
name = strings.Trim(name, `"'`)
val = strings.Trim(val, `"'`)
if name != "generator" || val == "" {
continue
}
if strings.Contains(val, "jlatex2html") ||
strings.Contains(val, "latex2html") ||
strings.Contains(val, "groff") ||
strings.Contains(val, "makeinfo") ||
strings.Contains(val, "texi2html") ||
strings.Contains(val, "ronn") ||
orgModeMetaRegex.MatchString(val) {
return true
}
}
return false
}
func isGeneratedJooq(_, ext string, content []byte) bool {
if ext != ".java" {
return false
}
for _, l := range getLines(content, 2) {
if bytes.Contains(l, []byte("This file is generated by jOOQ.")) {
return true
}
}
return false
}
func getFirstLine(content []byte) []byte {
lines := getLines(content, 1)
if len(lines) > 0 {
return lines[0]
}
return nil
}
// getLines returns up to the first n lines. A negative index will return up to
// the last n lines in reverse order.
func getLines(content []byte, n int) [][]byte {
var result [][]byte
if n < 0 {
for pos := len(content); pos > 0 && len(result) < -n; {
nlpos := bytes.LastIndexByte(content[:pos], '\n')
if nlpos+1 < len(content)-1 {
result = append(result, content[nlpos+1:pos])
}
pos = nlpos
}
} else {
for pos := 0; pos < len(content) && len(result) < n; {
nlpos := bytes.IndexByte(content[pos:], '\n')
if nlpos < 0 && pos < len(content) {
nlpos = len(content)
} else if nlpos >= 0 {
nlpos += pos
}
result = append(result, content[pos:nlpos])
pos = nlpos + 1
}
}
return result
}
func forEachLine(content []byte, cb func([]byte)) {
var pos int
for pos < len(content) {
nlpos := bytes.IndexByte(content[pos:], '\n')
if nlpos < 0 && pos < len(content) {
nlpos = len(content)
} else if nlpos >= 0 {
nlpos += pos
}
cb(content[pos:nlpos])
pos = nlpos + 1
}
}
func countAppearancesInLine(line []byte, targets ...string) int {
var count int
for _, t := range targets {
count += bytes.Count(line, []byte(t))
}
return count
}

17
vendor/github.com/go-enry/go-enry/v2/data/test.go generated vendored Normal file
View File

@@ -0,0 +1,17 @@
package data
import "github.com/go-enry/go-enry/v2/regex"
// TestMatchers is hand made collection of regexp used by the function `enry.IsTest`
// to identify test files in different languages.
var TestMatchers = []regex.EnryRegexp{
regex.MustCompile(`(^|/)tests/.*Test\.php$`),
regex.MustCompile(`(^|/)test/.*Test(s?)\.java$`),
regex.MustCompile(`(^|/)test(/|/.*/)Test.*\.java$`),
regex.MustCompile(`(^|/)test/.*(Test(s?)|Spec(s?))\.scala$`),
regex.MustCompile(`(^|/)test_.*\.py$`),
regex.MustCompile(`(^|/).*_test\.go$`),
regex.MustCompile(`(^|/).*_(test|spec)\.rb$`),
regex.MustCompile(`(^|/).*Test(s?)\.cs$`),
regex.MustCompile(`(^|/).*\.(test|spec)\.(ts|tsx|js)$`),
}

View File

@@ -3,167 +3,167 @@
package data
import "gopkg.in/toqueteos/substring.v1"
import "github.com/go-enry/go-enry/v2/regex"
var VendorMatchers = substring.Or(
substring.Regexp(`(^|/)cache/`),
substring.Regexp(`^[Dd]ependencies/`),
substring.Regexp(`(^|/)dist/`),
substring.Regexp(`^deps/`),
substring.Regexp(`(^|/)configure$`),
substring.Regexp(`(^|/)config.guess$`),
substring.Regexp(`(^|/)config.sub$`),
substring.Regexp(`(^|/)aclocal.m4`),
substring.Regexp(`(^|/)libtool.m4`),
substring.Regexp(`(^|/)ltoptions.m4`),
substring.Regexp(`(^|/)ltsugar.m4`),
substring.Regexp(`(^|/)ltversion.m4`),
substring.Regexp(`(^|/)lt~obsolete.m4`),
substring.Regexp(`dotnet-install\.(ps1|sh)$`),
substring.Regexp(`cpplint.py`),
substring.Regexp(`node_modules/`),
substring.Regexp(`(^|/)\.yarn/releases/`),
substring.Regexp(`(^|/)_esy$`),
substring.Regexp(`bower_components/`),
substring.Regexp(`^rebar$`),
substring.Regexp(`erlang.mk`),
substring.Regexp(`Godeps/_workspace/`),
substring.Regexp(`(^|/)testdata/`),
substring.Regexp(`.indent.pro`),
substring.Regexp(`(\.|-)min\.(js|css)$`),
substring.Regexp(`([^\s]*)import\.(css|less|scss|styl)$`),
substring.Regexp(`(^|/)bootstrap([^.]*)\.(js|css|less|scss|styl)$`),
substring.Regexp(`(^|/)custom\.bootstrap([^\s]*)(js|css|less|scss|styl)$`),
substring.Regexp(`(^|/)font-?awesome\.(css|less|scss|styl)$`),
substring.Regexp(`(^|/)font-?awesome/.*\.(css|less|scss|styl)$`),
substring.Regexp(`(^|/)foundation\.(css|less|scss|styl)$`),
substring.Regexp(`(^|/)normalize\.(css|less|scss|styl)$`),
substring.Regexp(`(^|/)skeleton\.(css|less|scss|styl)$`),
substring.Regexp(`(^|/)[Bb]ourbon/.*\.(css|less|scss|styl)$`),
substring.Regexp(`(^|/)animate\.(css|less|scss|styl)$`),
substring.Regexp(`(^|/)materialize\.(css|less|scss|styl|js)$`),
substring.Regexp(`(^|/)select2/.*\.(css|scss|js)$`),
substring.Regexp(`(^|/)bulma\.(css|sass|scss)$`),
substring.Regexp(`(3rd|[Tt]hird)[-_]?[Pp]arty/`),
substring.Regexp(`vendors?/`),
substring.Regexp(`extern(al)?/`),
substring.Regexp(`(^|/)[Vv]+endor/`),
substring.Regexp(`^debian/`),
substring.Regexp(`run.n$`),
substring.Regexp(`bootstrap-datepicker/`),
substring.Regexp(`(^|/)jquery([^.]*)\.js$`),
substring.Regexp(`(^|/)jquery\-\d\.\d+(\.\d+)?\.js$`),
substring.Regexp(`(^|/)jquery\-ui(\-\d\.\d+(\.\d+)?)?(\.\w+)?\.(js|css)$`),
substring.Regexp(`(^|/)jquery\.(ui|effects)\.([^.]*)\.(js|css)$`),
substring.Regexp(`jquery.fn.gantt.js`),
substring.Regexp(`jquery.fancybox.(js|css)`),
substring.Regexp(`fuelux.js`),
substring.Regexp(`(^|/)jquery\.fileupload(-\w+)?\.js$`),
substring.Regexp(`jquery.dataTables.js`),
substring.Regexp(`bootbox.js`),
substring.Regexp(`pdf.worker.js`),
substring.Regexp(`(^|/)slick\.\w+.js$`),
substring.Regexp(`(^|/)Leaflet\.Coordinates-\d+\.\d+\.\d+\.src\.js$`),
substring.Regexp(`leaflet.draw-src.js`),
substring.Regexp(`leaflet.draw.css`),
substring.Regexp(`Control.FullScreen.css`),
substring.Regexp(`Control.FullScreen.js`),
substring.Regexp(`leaflet.spin.js`),
substring.Regexp(`wicket-leaflet.js`),
substring.Regexp(`.sublime-project`),
substring.Regexp(`.sublime-workspace`),
substring.Regexp(`.vscode`),
substring.Regexp(`(^|/)prototype(.*)\.js$`),
substring.Regexp(`(^|/)effects\.js$`),
substring.Regexp(`(^|/)controls\.js$`),
substring.Regexp(`(^|/)dragdrop\.js$`),
substring.Regexp(`(.*?)\.d\.ts$`),
substring.Regexp(`(^|/)mootools([^.]*)\d+\.\d+.\d+([^.]*)\.js$`),
substring.Regexp(`(^|/)dojo\.js$`),
substring.Regexp(`(^|/)MochiKit\.js$`),
substring.Regexp(`(^|/)yahoo-([^.]*)\.js$`),
substring.Regexp(`(^|/)yui([^.]*)\.js$`),
substring.Regexp(`(^|/)ckeditor\.js$`),
substring.Regexp(`(^|/)tiny_mce([^.]*)\.js$`),
substring.Regexp(`(^|/)tiny_mce/(langs|plugins|themes|utils)`),
substring.Regexp(`(^|/)ace-builds/`),
substring.Regexp(`(^|/)fontello(.*?)\.css$`),
substring.Regexp(`(^|/)MathJax/`),
substring.Regexp(`(^|/)Chart\.js$`),
substring.Regexp(`(^|/)[Cc]ode[Mm]irror/(\d+\.\d+/)?(lib|mode|theme|addon|keymap|demo)`),
substring.Regexp(`(^|/)shBrush([^.]*)\.js$`),
substring.Regexp(`(^|/)shCore\.js$`),
substring.Regexp(`(^|/)shLegacy\.js$`),
substring.Regexp(`(^|/)angular([^.]*)\.js$`),
substring.Regexp(`(^|\/)d3(\.v\d+)?([^.]*)\.js$`),
substring.Regexp(`(^|/)react(-[^.]*)?\.js$`),
substring.Regexp(`(^|/)flow-typed/.*\.js$`),
substring.Regexp(`(^|/)modernizr\-\d\.\d+(\.\d+)?\.js$`),
substring.Regexp(`(^|/)modernizr\.custom\.\d+\.js$`),
substring.Regexp(`(^|/)knockout-(\d+\.){3}(debug\.)?js$`),
substring.Regexp(`(^|/)docs?/_?(build|themes?|templates?|static)/`),
substring.Regexp(`(^|/)admin_media/`),
substring.Regexp(`(^|/)env/`),
substring.Regexp(`^fabfile\.py$`),
substring.Regexp(`^waf$`),
substring.Regexp(`^.osx$`),
substring.Regexp(`\.xctemplate/`),
substring.Regexp(`\.imageset/`),
substring.Regexp(`(^|/)Carthage/`),
substring.Regexp(`(^|/)Sparkle/`),
substring.Regexp(`Crashlytics.framework/`),
substring.Regexp(`Fabric.framework/`),
substring.Regexp(`BuddyBuildSDK.framework/`),
substring.Regexp(`Realm.framework`),
substring.Regexp(`RealmSwift.framework`),
substring.Regexp(`gitattributes$`),
substring.Regexp(`gitignore$`),
substring.Regexp(`gitmodules$`),
substring.Regexp(`(^|/)gradlew$`),
substring.Regexp(`(^|/)gradlew\.bat$`),
substring.Regexp(`(^|/)gradle/wrapper/`),
substring.Regexp(`(^|/)mvnw$`),
substring.Regexp(`(^|/)mvnw\.cmd$`),
substring.Regexp(`(^|/)\.mvn/wrapper/`),
substring.Regexp(`-vsdoc\.js$`),
substring.Regexp(`\.intellisense\.js$`),
substring.Regexp(`(^|/)jquery([^.]*)\.validate(\.unobtrusive)?\.js$`),
substring.Regexp(`(^|/)jquery([^.]*)\.unobtrusive\-ajax\.js$`),
substring.Regexp(`(^|/)[Mm]icrosoft([Mm]vc)?([Aa]jax|[Vv]alidation)(\.debug)?\.js$`),
substring.Regexp(`^[Pp]ackages\/.+\.\d+\/`),
substring.Regexp(`(^|/)extjs/.*?\.js$`),
substring.Regexp(`(^|/)extjs/.*?\.xml$`),
substring.Regexp(`(^|/)extjs/.*?\.txt$`),
substring.Regexp(`(^|/)extjs/.*?\.html$`),
substring.Regexp(`(^|/)extjs/.*?\.properties$`),
substring.Regexp(`(^|/)extjs/.sencha/`),
substring.Regexp(`(^|/)extjs/docs/`),
substring.Regexp(`(^|/)extjs/builds/`),
substring.Regexp(`(^|/)extjs/cmd/`),
substring.Regexp(`(^|/)extjs/examples/`),
substring.Regexp(`(^|/)extjs/locale/`),
substring.Regexp(`(^|/)extjs/packages/`),
substring.Regexp(`(^|/)extjs/plugins/`),
substring.Regexp(`(^|/)extjs/resources/`),
substring.Regexp(`(^|/)extjs/src/`),
substring.Regexp(`(^|/)extjs/welcome/`),
substring.Regexp(`(^|/)html5shiv\.js$`),
substring.Regexp(`^[Tt]ests?/fixtures/`),
substring.Regexp(`^[Ss]pecs?/fixtures/`),
substring.Regexp(`(^|/)cordova([^.]*)\.js$`),
substring.Regexp(`(^|/)cordova\-\d\.\d(\.\d)?\.js$`),
substring.Regexp(`foundation(\..*)?\.js$`),
substring.Regexp(`^Vagrantfile$`),
substring.Regexp(`.[Dd][Ss]_[Ss]tore$`),
substring.Regexp(`^vignettes/`),
substring.Regexp(`^inst/extdata/`),
substring.Regexp(`octicons.css`),
substring.Regexp(`sprockets-octicons.scss`),
substring.Regexp(`(^|/)activator$`),
substring.Regexp(`(^|/)activator\.bat$`),
substring.Regexp(`proguard.pro`),
substring.Regexp(`proguard-rules.pro`),
substring.Regexp(`^puphpet/`),
substring.Regexp(`(^|/)\.google_apis/`),
substring.Regexp(`^Jenkinsfile$`),
)
var VendorMatchers = []regex.EnryRegexp{
regex.MustCompile(`(^|/)cache/`),
regex.MustCompile(`^[Dd]ependencies/`),
regex.MustCompile(`(^|/)dist/`),
regex.MustCompile(`^deps/`),
regex.MustCompile(`(^|/)configure$`),
regex.MustCompile(`(^|/)config.guess$`),
regex.MustCompile(`(^|/)config.sub$`),
regex.MustCompile(`(^|/)aclocal.m4`),
regex.MustCompile(`(^|/)libtool.m4`),
regex.MustCompile(`(^|/)ltoptions.m4`),
regex.MustCompile(`(^|/)ltsugar.m4`),
regex.MustCompile(`(^|/)ltversion.m4`),
regex.MustCompile(`(^|/)lt~obsolete.m4`),
regex.MustCompile(`dotnet-install\.(ps1|sh)$`),
regex.MustCompile(`cpplint.py`),
regex.MustCompile(`node_modules/`),
regex.MustCompile(`(^|/)\.yarn/releases/`),
regex.MustCompile(`(^|/)_esy$`),
regex.MustCompile(`bower_components/`),
regex.MustCompile(`^rebar$`),
regex.MustCompile(`erlang.mk`),
regex.MustCompile(`Godeps/_workspace/`),
regex.MustCompile(`(^|/)testdata/`),
regex.MustCompile(`.indent.pro`),
regex.MustCompile(`(\.|-)min\.(js|css)$`),
regex.MustCompile(`([^\s]*)import\.(css|less|scss|styl)$`),
regex.MustCompile(`(^|/)bootstrap([^.]*)\.(js|css|less|scss|styl)$`),
regex.MustCompile(`(^|/)custom\.bootstrap([^\s]*)(js|css|less|scss|styl)$`),
regex.MustCompile(`(^|/)font-?awesome\.(css|less|scss|styl)$`),
regex.MustCompile(`(^|/)font-?awesome/.*\.(css|less|scss|styl)$`),
regex.MustCompile(`(^|/)foundation\.(css|less|scss|styl)$`),
regex.MustCompile(`(^|/)normalize\.(css|less|scss|styl)$`),
regex.MustCompile(`(^|/)skeleton\.(css|less|scss|styl)$`),
regex.MustCompile(`(^|/)[Bb]ourbon/.*\.(css|less|scss|styl)$`),
regex.MustCompile(`(^|/)animate\.(css|less|scss|styl)$`),
regex.MustCompile(`(^|/)materialize\.(css|less|scss|styl|js)$`),
regex.MustCompile(`(^|/)select2/.*\.(css|scss|js)$`),
regex.MustCompile(`(^|/)bulma\.(css|sass|scss)$`),
regex.MustCompile(`(3rd|[Tt]hird)[-_]?[Pp]arty/`),
regex.MustCompile(`vendors?/`),
regex.MustCompile(`extern(al)?/`),
regex.MustCompile(`(^|/)[Vv]+endor/`),
regex.MustCompile(`^debian/`),
regex.MustCompile(`run.n$`),
regex.MustCompile(`bootstrap-datepicker/`),
regex.MustCompile(`(^|/)jquery([^.]*)\.js$`),
regex.MustCompile(`(^|/)jquery\-\d\.\d+(\.\d+)?\.js$`),
regex.MustCompile(`(^|/)jquery\-ui(\-\d\.\d+(\.\d+)?)?(\.\w+)?\.(js|css)$`),
regex.MustCompile(`(^|/)jquery\.(ui|effects)\.([^.]*)\.(js|css)$`),
regex.MustCompile(`jquery.fn.gantt.js`),
regex.MustCompile(`jquery.fancybox.(js|css)`),
regex.MustCompile(`fuelux.js`),
regex.MustCompile(`(^|/)jquery\.fileupload(-\w+)?\.js$`),
regex.MustCompile(`jquery.dataTables.js`),
regex.MustCompile(`bootbox.js`),
regex.MustCompile(`pdf.worker.js`),
regex.MustCompile(`(^|/)slick\.\w+.js$`),
regex.MustCompile(`(^|/)Leaflet\.Coordinates-\d+\.\d+\.\d+\.src\.js$`),
regex.MustCompile(`leaflet.draw-src.js`),
regex.MustCompile(`leaflet.draw.css`),
regex.MustCompile(`Control.FullScreen.css`),
regex.MustCompile(`Control.FullScreen.js`),
regex.MustCompile(`leaflet.spin.js`),
regex.MustCompile(`wicket-leaflet.js`),
regex.MustCompile(`.sublime-project`),
regex.MustCompile(`.sublime-workspace`),
regex.MustCompile(`.vscode`),
regex.MustCompile(`(^|/)prototype(.*)\.js$`),
regex.MustCompile(`(^|/)effects\.js$`),
regex.MustCompile(`(^|/)controls\.js$`),
regex.MustCompile(`(^|/)dragdrop\.js$`),
regex.MustCompile(`(.*?)\.d\.ts$`),
regex.MustCompile(`(^|/)mootools([^.]*)\d+\.\d+.\d+([^.]*)\.js$`),
regex.MustCompile(`(^|/)dojo\.js$`),
regex.MustCompile(`(^|/)MochiKit\.js$`),
regex.MustCompile(`(^|/)yahoo-([^.]*)\.js$`),
regex.MustCompile(`(^|/)yui([^.]*)\.js$`),
regex.MustCompile(`(^|/)ckeditor\.js$`),
regex.MustCompile(`(^|/)tiny_mce([^.]*)\.js$`),
regex.MustCompile(`(^|/)tiny_mce/(langs|plugins|themes|utils)`),
regex.MustCompile(`(^|/)ace-builds/`),
regex.MustCompile(`(^|/)fontello(.*?)\.css$`),
regex.MustCompile(`(^|/)MathJax/`),
regex.MustCompile(`(^|/)Chart\.js$`),
regex.MustCompile(`(^|/)[Cc]ode[Mm]irror/(\d+\.\d+/)?(lib|mode|theme|addon|keymap|demo)`),
regex.MustCompile(`(^|/)shBrush([^.]*)\.js$`),
regex.MustCompile(`(^|/)shCore\.js$`),
regex.MustCompile(`(^|/)shLegacy\.js$`),
regex.MustCompile(`(^|/)angular([^.]*)\.js$`),
regex.MustCompile(`(^|\/)d3(\.v\d+)?([^.]*)\.js$`),
regex.MustCompile(`(^|/)react(-[^.]*)?\.js$`),
regex.MustCompile(`(^|/)flow-typed/.*\.js$`),
regex.MustCompile(`(^|/)modernizr\-\d\.\d+(\.\d+)?\.js$`),
regex.MustCompile(`(^|/)modernizr\.custom\.\d+\.js$`),
regex.MustCompile(`(^|/)knockout-(\d+\.){3}(debug\.)?js$`),
regex.MustCompile(`(^|/)docs?/_?(build|themes?|templates?|static)/`),
regex.MustCompile(`(^|/)admin_media/`),
regex.MustCompile(`(^|/)env/`),
regex.MustCompile(`^fabfile\.py$`),
regex.MustCompile(`^waf$`),
regex.MustCompile(`^.osx$`),
regex.MustCompile(`\.xctemplate/`),
regex.MustCompile(`\.imageset/`),
regex.MustCompile(`(^|/)Carthage/`),
regex.MustCompile(`(^|/)Sparkle/`),
regex.MustCompile(`Crashlytics.framework/`),
regex.MustCompile(`Fabric.framework/`),
regex.MustCompile(`BuddyBuildSDK.framework/`),
regex.MustCompile(`Realm.framework`),
regex.MustCompile(`RealmSwift.framework`),
regex.MustCompile(`gitattributes$`),
regex.MustCompile(`gitignore$`),
regex.MustCompile(`gitmodules$`),
regex.MustCompile(`(^|/)gradlew$`),
regex.MustCompile(`(^|/)gradlew\.bat$`),
regex.MustCompile(`(^|/)gradle/wrapper/`),
regex.MustCompile(`(^|/)mvnw$`),
regex.MustCompile(`(^|/)mvnw\.cmd$`),
regex.MustCompile(`(^|/)\.mvn/wrapper/`),
regex.MustCompile(`-vsdoc\.js$`),
regex.MustCompile(`\.intellisense\.js$`),
regex.MustCompile(`(^|/)jquery([^.]*)\.validate(\.unobtrusive)?\.js$`),
regex.MustCompile(`(^|/)jquery([^.]*)\.unobtrusive\-ajax\.js$`),
regex.MustCompile(`(^|/)[Mm]icrosoft([Mm]vc)?([Aa]jax|[Vv]alidation)(\.debug)?\.js$`),
regex.MustCompile(`^[Pp]ackages\/.+\.\d+\/`),
regex.MustCompile(`(^|/)extjs/.*?\.js$`),
regex.MustCompile(`(^|/)extjs/.*?\.xml$`),
regex.MustCompile(`(^|/)extjs/.*?\.txt$`),
regex.MustCompile(`(^|/)extjs/.*?\.html$`),
regex.MustCompile(`(^|/)extjs/.*?\.properties$`),
regex.MustCompile(`(^|/)extjs/.sencha/`),
regex.MustCompile(`(^|/)extjs/docs/`),
regex.MustCompile(`(^|/)extjs/builds/`),
regex.MustCompile(`(^|/)extjs/cmd/`),
regex.MustCompile(`(^|/)extjs/examples/`),
regex.MustCompile(`(^|/)extjs/locale/`),
regex.MustCompile(`(^|/)extjs/packages/`),
regex.MustCompile(`(^|/)extjs/plugins/`),
regex.MustCompile(`(^|/)extjs/resources/`),
regex.MustCompile(`(^|/)extjs/src/`),
regex.MustCompile(`(^|/)extjs/welcome/`),
regex.MustCompile(`(^|/)html5shiv\.js$`),
regex.MustCompile(`^[Tt]ests?/fixtures/`),
regex.MustCompile(`^[Ss]pecs?/fixtures/`),
regex.MustCompile(`(^|/)cordova([^.]*)\.js$`),
regex.MustCompile(`(^|/)cordova\-\d\.\d(\.\d)?\.js$`),
regex.MustCompile(`foundation(\..*)?\.js$`),
regex.MustCompile(`^Vagrantfile$`),
regex.MustCompile(`.[Dd][Ss]_[Ss]tore$`),
regex.MustCompile(`^vignettes/`),
regex.MustCompile(`^inst/extdata/`),
regex.MustCompile(`octicons.css`),
regex.MustCompile(`sprockets-octicons.scss`),
regex.MustCompile(`(^|/)activator$`),
regex.MustCompile(`(^|/)activator\.bat$`),
regex.MustCompile(`proguard.pro`),
regex.MustCompile(`proguard-rules.pro`),
regex.MustCompile(`^puphpet/`),
regex.MustCompile(`(^|/)\.google_apis/`),
regex.MustCompile(`^Jenkinsfile$`),
}

View File

@@ -3,9 +3,7 @@ module github.com/go-enry/go-enry/v2
go 1.14
require (
github.com/go-enry/go-oniguruma v1.2.0
github.com/go-enry/go-oniguruma v1.2.1
github.com/stretchr/testify v1.3.0
github.com/toqueteos/trie v1.0.0 // indirect
gopkg.in/toqueteos/substring.v1 v1.0.2
gopkg.in/yaml.v2 v2.2.8
)

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