You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

699 lines
25 KiB

Pull request review/approval and comment on code (#3748) * Initial ui components for pull request review * Add Review Add IssueComment types Signed-off-by: Jonas Franz <info@jonasfranz.software> (cherry picked from commit 2b4daab) Signed-off-by: Jonas Franz <info@jonasfranz.software> * Replace ReviewComment with Content Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add load functions Add ReviewID to findComments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add create review comment implementation Add migration for review Other small changes Signed-off-by: Jonas Franz <info@jonasfranz.software> * Simplified create and find functions for review Signed-off-by: Jonas Franz <info@jonasfranz.software> * Moved "Pending" to first position Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add GetCurrentReview to simplify fetching current review Signed-off-by: Jonas Franz <info@jonasfranz.software> * Preview for listing comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Move new comment form to its own file Signed-off-by: Jonas Franz <info@jonasfranz.software> * Implement Review form Show Review comments on comment stream Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for single comments Showing buttons in context Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add pending tag to pending review comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add unit tests for Review Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fetch all review ids at once Add unit tests Signed-off-by: Jonas Franz <info@jonasfranz.software> * gofmt Signed-off-by: Jonas Franz <info@jonasfranz.software> * Improved comment rendering in "Files" view by adding Comments to DiffLine Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for invalidating comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Switched back to code.gitea.io/git Signed-off-by: Jonas Franz <info@jonasfranz.software> * Moved review migration from v64 to v65 Signed-off-by: Jonas Franz <info@jonasfranz.software> * Rebuild css Signed-off-by: Jonas Franz <info@jonasfranz.software> * gofmt Signed-off-by: Jonas Franz <info@jonasfranz.software> * Improve translations Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix unit tests by updating fixtures and updating outdated test Signed-off-by: Jonas Franz <info@jonasfranz.software> * Comments will be shown at the right place now Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for deleting CodeComments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix problems caused by files in subdirectories Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for showing code comments of reviews in conversation Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for "Show/Hide outdated" Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update code.gitea.io/git Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for new webhooks Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update comparison Signed-off-by: Jonas Franz <info@jonasfranz.software> * Resolve conflicts Signed-off-by: Jonas Franz <info@jonasfranz.software> * Minor UI improvements * update code.gitea.io/git * Fix ui bug reported by @lunny causing wrong position of add button Add functionality to "Cancel" button Add scale effects to add button Hide "Cancel" button for existing comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Prepare solving conflicts Signed-off-by: Jonas Franz <info@jonasfranz.software> * Show add button only if no comments already exist for the line Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add missing vendor files Signed-off-by: Jonas Franz <info@jonasfranz.software> * Check if reviewer is nil Signed-off-by: Jonas Franz <info@jonasfranz.software> * Show forms only to users who are logged in Signed-off-by: Jonas Franz <info@jonasfranz.software> * Revert "Show forms only to users who are logged in" This reverts commit c083682 Signed-off-by: Jonas Franz <info@jonasfranz.software> * Save patch in comment Render patch for code comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add link to comment in code Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add reply form to comment list Show forms only to signed in users Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add 'Reply' as translatable Add CODE_COMMENT_LINES setting Signed-off-by: Jonas Franz <info@jonasfranz.software> * gofmt Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix problems introduced by checking for singed in user Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add v70 Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update generated stylesheet Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix preview Beginn with new review comment patch system Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add new algo to generate diff for line range Remove old algo used for cutting big diffs (it was very buggy) * Add documentation and example for CutDiffAroundLine * Fix example of CutDiffAroundLine * Fix some comment UI rendering bugs * Add code comment edit mode * Send notifications / actions to users until review gets published Fix diff generation bug Fix wrong hashtag * Fix vet errors * Send notifications also for single comments * Fix some notification bugs, fix link * Fix: add comment icon is only shown on code lines * Add lint comment * Add unit tests for git diff * Add more error messages * Regenerated css Signed-off-by: Jonas Franz <info@jonasfranz.software> * fmt Signed-off-by: Jonas Franz <info@jonasfranz.software> * Regenerated CSS with latest less version Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix test by updating comment type to new ID Signed-off-by: Jonas Franz <info@jonasfranz.software> * Introducing CodeComments as type for map[string]map[int64][]*Comment Other minor code improvements Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix data-tab issues Signed-off-by: Jonas Franz <info@jonasfranz.software> * Remove unnecessary change Signed-off-by: Jonas Franz <info@jonasfranz.software> * refactored checkForInvalidation Signed-off-by: Jonas Franz <info@jonasfranz.software> * Append comments instead of setting Signed-off-by: Jonas Franz <info@jonasfranz.software> * Use HeadRepo instead of BaseRepo Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update migration Signed-off-by: Jonas Franz <info@jonasfranz.de> * Regenerated CSS Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add copyright Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update index.css Signed-off-by: Jonas Franz <info@jonasfranz.software>
5 years ago
Pull request review/approval and comment on code (#3748) * Initial ui components for pull request review * Add Review Add IssueComment types Signed-off-by: Jonas Franz <info@jonasfranz.software> (cherry picked from commit 2b4daab) Signed-off-by: Jonas Franz <info@jonasfranz.software> * Replace ReviewComment with Content Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add load functions Add ReviewID to findComments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add create review comment implementation Add migration for review Other small changes Signed-off-by: Jonas Franz <info@jonasfranz.software> * Simplified create and find functions for review Signed-off-by: Jonas Franz <info@jonasfranz.software> * Moved "Pending" to first position Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add GetCurrentReview to simplify fetching current review Signed-off-by: Jonas Franz <info@jonasfranz.software> * Preview for listing comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Move new comment form to its own file Signed-off-by: Jonas Franz <info@jonasfranz.software> * Implement Review form Show Review comments on comment stream Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for single comments Showing buttons in context Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add pending tag to pending review comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add unit tests for Review Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fetch all review ids at once Add unit tests Signed-off-by: Jonas Franz <info@jonasfranz.software> * gofmt Signed-off-by: Jonas Franz <info@jonasfranz.software> * Improved comment rendering in "Files" view by adding Comments to DiffLine Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for invalidating comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Switched back to code.gitea.io/git Signed-off-by: Jonas Franz <info@jonasfranz.software> * Moved review migration from v64 to v65 Signed-off-by: Jonas Franz <info@jonasfranz.software> * Rebuild css Signed-off-by: Jonas Franz <info@jonasfranz.software> * gofmt Signed-off-by: Jonas Franz <info@jonasfranz.software> * Improve translations Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix unit tests by updating fixtures and updating outdated test Signed-off-by: Jonas Franz <info@jonasfranz.software> * Comments will be shown at the right place now Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for deleting CodeComments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix problems caused by files in subdirectories Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for showing code comments of reviews in conversation Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for "Show/Hide outdated" Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update code.gitea.io/git Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add support for new webhooks Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update comparison Signed-off-by: Jonas Franz <info@jonasfranz.software> * Resolve conflicts Signed-off-by: Jonas Franz <info@jonasfranz.software> * Minor UI improvements * update code.gitea.io/git * Fix ui bug reported by @lunny causing wrong position of add button Add functionality to "Cancel" button Add scale effects to add button Hide "Cancel" button for existing comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Prepare solving conflicts Signed-off-by: Jonas Franz <info@jonasfranz.software> * Show add button only if no comments already exist for the line Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add missing vendor files Signed-off-by: Jonas Franz <info@jonasfranz.software> * Check if reviewer is nil Signed-off-by: Jonas Franz <info@jonasfranz.software> * Show forms only to users who are logged in Signed-off-by: Jonas Franz <info@jonasfranz.software> * Revert "Show forms only to users who are logged in" This reverts commit c083682 Signed-off-by: Jonas Franz <info@jonasfranz.software> * Save patch in comment Render patch for code comments Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add link to comment in code Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add reply form to comment list Show forms only to signed in users Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add 'Reply' as translatable Add CODE_COMMENT_LINES setting Signed-off-by: Jonas Franz <info@jonasfranz.software> * gofmt Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix problems introduced by checking for singed in user Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add v70 Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update generated stylesheet Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix preview Beginn with new review comment patch system Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add new algo to generate diff for line range Remove old algo used for cutting big diffs (it was very buggy) * Add documentation and example for CutDiffAroundLine * Fix example of CutDiffAroundLine * Fix some comment UI rendering bugs * Add code comment edit mode * Send notifications / actions to users until review gets published Fix diff generation bug Fix wrong hashtag * Fix vet errors * Send notifications also for single comments * Fix some notification bugs, fix link * Fix: add comment icon is only shown on code lines * Add lint comment * Add unit tests for git diff * Add more error messages * Regenerated css Signed-off-by: Jonas Franz <info@jonasfranz.software> * fmt Signed-off-by: Jonas Franz <info@jonasfranz.software> * Regenerated CSS with latest less version Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix test by updating comment type to new ID Signed-off-by: Jonas Franz <info@jonasfranz.software> * Introducing CodeComments as type for map[string]map[int64][]*Comment Other minor code improvements Signed-off-by: Jonas Franz <info@jonasfranz.software> * Fix data-tab issues Signed-off-by: Jonas Franz <info@jonasfranz.software> * Remove unnecessary change Signed-off-by: Jonas Franz <info@jonasfranz.software> * refactored checkForInvalidation Signed-off-by: Jonas Franz <info@jonasfranz.software> * Append comments instead of setting Signed-off-by: Jonas Franz <info@jonasfranz.software> * Use HeadRepo instead of BaseRepo Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update migration Signed-off-by: Jonas Franz <info@jonasfranz.de> * Regenerated CSS Signed-off-by: Jonas Franz <info@jonasfranz.software> * Add copyright Signed-off-by: Jonas Franz <info@jonasfranz.software> * Update index.css Signed-off-by: Jonas Franz <info@jonasfranz.software>
5 years ago
Repository avatars (#6986) * Repository avatars - first variant of code from old work for gogs - add migration 87 - add new option in app.ini - add en-US locale string - add new class in repository.less * Add changed index.css, remove unused template name * Update en-us doc about configuration options * Add comments to new functions, add new option to docker app.ini * Add comment for lint * Remove variable, not needed * Fix formatting * Update swagger api template * Check if avatar exists * Fix avatar link/path checks * Typo * TEXT column can't have a default value * Fixes: - remove old avatar file on upload - use ID in name of avatar file - users may upload same files - add simple tests * Fix fmt check * Generate PNG instead of "static" GIF * More informative comment * Fix error message * Update avatar upload checks: - add file size check - add new option - update config docs - add new string to en-us locale * Fixes: - use FileHEader field for check file size - add new test - upload big image * Fix formatting * Update comments * Update log message * Removed wrong style - not needed * Use Sync2 to migrate * Update repos list view - bigger avatar - fix html blocks alignment * A little adjust avatar size * Use small icons for explore/repo list * Use new cool avatar preparation func by @lafriks * Missing changes for new function * Remove unused import, move imports * Missed new option definition in app.ini Add file size check in user/profile avatar upload * Use smaller field length for Avatar * Use session to update repo DB data, update DeleteAvatar - use session too * Fix err variable definition * As suggested @lafriks - return as soon as possible, code readability
5 years ago
Template Repositories (#8768) * Start work on templates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Continue work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix IsTemplate vs IsGenerated Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tabs vs spaces * Tabs vs Spaces * Add templates to API & start adding tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix integration tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove unused User Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move template tests to existing repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Minor re-check updates and cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix optionalbool Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test fixes and icon change Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add new user and repo for tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests (finally) Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update meta repo with env variables Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move generation to create page Combine with repo create template Modify API search to prioritize owner for repo Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests and coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger and JS lint Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix API searching for own private repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Change wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix repo search test. User had a private repo that didn't show up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Another search test fix Signed-off-by: jolheiser <john.olheiser@gmail.com> * Clarify git content Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Feedback updates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add topics WIP Signed-off-by: jolheiser <john.olheiser@gmail.com> * Finish adding topics Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update locale Signed-off-by: jolheiser <john.olheiser@gmail.com>
4 years ago
Change target branch for pull request (#6488) * Adds functionality to change target branch of created pull requests Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use const instead of var in JavaScript additions Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Check if branches are equal and if PR already exists before changing target branch Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Make sure to check all commits Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Print error messages for user as error flash message Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Disallow changing target branch of closed or merged pull requests Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Resolve conflicts after merge of upstream/master Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Change order of branch select fields Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes duplicate check Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use ctx.Tr for translations Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Recompile JS Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Use correct translation namespace Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Remove redundant if condition Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Moves most change branch logic into pull service Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Completes comment Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Add Ref to ChangesPayload for logging changed target branches instead of creating a new struct Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Revert changes to go.mod Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Directly use createComment method Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Return 404 if pull request is not found. Move written check up Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Remove variable declaration Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Return client errors on change pull request target errors Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Return error in commit.HasPreviousCommit Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adds blank line Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Test patch before persisting new target branch Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Update patch before testing (not working) Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes patch calls when changeing pull request target Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Removes unneeded check for base name Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Moves ChangeTargetBranch completely to pull service. Update patch status. Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Set webhook mode after errors were validated Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Update PR in one transaction Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Move logic for check if head is equal with branch to pull model Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adds missing comment and simplify return Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com> * Adjust CreateComment method call Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
4 years ago
Restricted users (#6274) * Restricted users (#4334): initial implementation * Add User.IsRestricted & UI to edit it * Pass user object instead of user id to places where IsRestricted flag matters * Restricted users: maintain access rows for all referenced repos (incl public) * Take logged in user & IsRestricted flag into account in org/repo listings, searches and accesses * Add basic repo access tests for restricted users Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Mention restricted users in the faq Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert unnecessary change `.isUserPartOfOrg` -> `.IsUserPartOfOrg` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Remove unnecessary `org.IsOrganization()` call Signed-off-by: Manush Dodunekov <manush@stendahls.se> * Revert to an `int64` keyed `accessMap` * Add type `userAccess` * Add convenience func updateUserAccess() * Turn accessMap into a `map[int64]userAccess` Signed-off-by: Manush Dodunekov <manush@stendahls.se> * or even better: `map[int64]*userAccess` * updateUserAccess(): use tighter syntax as suggested by lafriks * even tighter * Avoid extra loop * Don't disclose limited orgs to unauthenticated users * Don't assume block only applies to orgs * Use an array of `VisibleType` for filtering * fix yet another thinko * Ok - no need for u * Revert "Ok - no need for u" This reverts commit 5c3e886aabd5acd997a3b35687d322439732c200. Co-authored-by: Antoine GIRARD <sapk@users.noreply.github.com> Co-authored-by: Lauris BH <lauris@nix.lv>
4 years ago
Add Organization Wide Labels (#10814) * Add organization wide labels Implement organization wide labels similar to organization wide webhooks. This lets you create individual labels for organizations that can be used for all repos under that organization (so being able to reuse the same label across multiple repos). This makes it possible for small organizations with many repos to use labels effectively. Fixes #7406 * Add migration * remove comments * fix tests * Update options/locale/locale_en-US.ini Removed unused translation string * show org labels in issue search label filter * Use more clear var name * rename migration after merge from master * comment typo * update migration again after rebase with master * check for orgID <=0 per guillep2k review * fmt * Apply suggestions from code review Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * remove unused code * Make sure RepoID is 0 when searching orgID per code review * more changes/code review requests * More descriptive translation var per code review * func description/delete comment when issue label deleted instead of hiding it * remove comment * only use issues in that repo when calculating number of open issues for org label on repo label page * Add integration test for IssuesSearch API with labels * remove unused function * Update models/issue_label.go Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Use subquery in GetLabelIDsInReposByNames * Fix tests to use correct orgID * fix more tests * IssuesSearch api now uses new BuildLabelNamesIssueIDsCondition. Add a few more tests as well * update comment for clarity * Revert previous code change now that we can use the new BuildLabelNamesIssueIDsCondition * Don't sort repos by date in IssuesSearch API After much debugging I've found a strange issue where in some cases MySQL will return a different result than other enigines if a query is sorted by a null collumn. For example with our integration test data where we don't set updated_unix in repository fixtures: SELECT `id`, `owner_id`, `owner_name`, `lower_name`, `name`, `description`, `website`, `original_service_type`, `original_url`, `default_branch`, `num_watches`, `num_stars`, `num_forks`, `num_issues`, `num_closed_issues`, `num_pulls`, `num_closed_pulls`, `num_milestones`, `num_closed_milestones`, `is_private`, `is_empty`, `is_archived`, `is_mirror`, `status`, `is_fork`, `fork_id`, `is_template`, `template_id`, `size`, `is_fsck_enabled`, `close_issues_via_commit_in_any_branch`, `topics`, `avatar`, `created_unix`, `updated_unix` FROM `repository` ORDER BY updated_unix DESC LIMIT 15 OFFSET 45 Returns different results for MySQL than other engines. However, the similar query: SELECT `id`, `owner_id`, `owner_name`, `lower_name`, `name`, `description`, `website`, `original_service_type`, `original_url`, `default_branch`, `num_watches`, `num_stars`, `num_forks`, `num_issues`, `num_closed_issues`, `num_pulls`, `num_closed_pulls`, `num_milestones`, `num_closed_milestones`, `is_private`, `is_empty`, `is_archived`, `is_mirror`, `status`, `is_fork`, `fork_id`, `is_template`, `template_id`, `size`, `is_fsck_enabled`, `close_issues_via_commit_in_any_branch`, `topics`, `avatar`, `created_unix`, `updated_unix` FROM `repository` ORDER BY updated_unix DESC LIMIT 15 OFFSET 30 Returns the same results. This causes integration tests to fail on MySQL in certain cases but would never show up in a real installation. Since this API call always returns issues based on the optionally provided repo_priority_id or the issueID itself, there is no change to results by changing the repo sorting method used to get ids earlier in the function. * linter is back! * code review * remove now unused option * Fix newline at end of files * more unused code * update to master * check for matching ids before query * Update models/issue_label.go Co-Authored-By: 6543 <6543@obermui.de> * Update models/issue_label.go * update comments * Update routers/org/setting.go Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> Co-authored-by: 6543 <6543@obermui.de>
4 years ago
Better logging (#6038) (#6095) * Panic don't fatal on create new logger Fixes #5854 Signed-off-by: Andrew Thornton <art27@cantab.net> * partial broken * Update the logging infrastrcture Signed-off-by: Andrew Thornton <art27@cantab.net> * Reset the skip levels for Fatal and Error Signed-off-by: Andrew Thornton <art27@cantab.net> * broken ncsa * More log.Error fixes Signed-off-by: Andrew Thornton <art27@cantab.net> * Remove nal * set log-levels to lowercase * Make console_test test all levels * switch to lowercased levels * OK now working * Fix vetting issues * Fix lint * Fix tests * change default logging to match current gitea * Improve log testing Signed-off-by: Andrew Thornton <art27@cantab.net> * reset error skip levels to 0 * Update documentation and access logger configuration * Redirect the router log back to gitea if redirect macaron log but also allow setting the log level - i.e. TRACE * Fix broken level caching * Refactor the router log * Add Router logger * Add colorizing options * Adjust router colors * Only create logger if they will be used * update app.ini.sample * rename Attribute ColorAttribute * Change from white to green for function * Set fatal/error levels * Restore initial trace logger * Fix Trace arguments in modules/auth/auth.go * Properly handle XORMLogger * Improve admin/config page * fix fmt * Add auto-compression of old logs * Update error log levels * Remove the unnecessary skip argument from Error, Fatal and Critical * Add stacktrace support * Fix tests * Remove x/sync from vendors? * Add stderr option to console logger * Use filepath.ToSlash to protect against Windows in tests * Remove prefixed underscores from names in colors.go * Remove not implemented database logger This was removed from Gogs on 4 Mar 2016 but left in the configuration since then. * Ensure that log paths are relative to ROOT_PATH * use path.Join * rename jsonConfig to logConfig * Rename "config" to "jsonConfig" to make it clearer * Requested changes * Requested changes: XormLogger * Try to color the windows terminal If successful default to colorizing the console logs * fixup * Colorize initially too * update vendor * Colorize logs on default and remove if this is not a colorizing logger * Fix documentation * fix test * Use go-isatty to detect if on windows we are on msys or cygwin * Fix spelling mistake * Add missing vendors * More changes * Rationalise the ANSI writer protection * Adjust colors on advice from @0x5c * Make Flags a comma separated list * Move to use the windows constant for ENABLE_VIRTUAL_TERMINAL_PROCESSING * Ensure matching is done on the non-colored message - to simpify EXPRESSION
5 years ago
Better logging (#6038) (#6095) * Panic don't fatal on create new logger Fixes #5854 Signed-off-by: Andrew Thornton <art27@cantab.net> * partial broken * Update the logging infrastrcture Signed-off-by: Andrew Thornton <art27@cantab.net> * Reset the skip levels for Fatal and Error Signed-off-by: Andrew Thornton <art27@cantab.net> * broken ncsa * More log.Error fixes Signed-off-by: Andrew Thornton <art27@cantab.net> * Remove nal * set log-levels to lowercase * Make console_test test all levels * switch to lowercased levels * OK now working * Fix vetting issues * Fix lint * Fix tests * change default logging to match current gitea * Improve log testing Signed-off-by: Andrew Thornton <art27@cantab.net> * reset error skip levels to 0 * Update documentation and access logger configuration * Redirect the router log back to gitea if redirect macaron log but also allow setting the log level - i.e. TRACE * Fix broken level caching * Refactor the router log * Add Router logger * Add colorizing options * Adjust router colors * Only create logger if they will be used * update app.ini.sample * rename Attribute ColorAttribute * Change from white to green for function * Set fatal/error levels * Restore initial trace logger * Fix Trace arguments in modules/auth/auth.go * Properly handle XORMLogger * Improve admin/config page * fix fmt * Add auto-compression of old logs * Update error log levels * Remove the unnecessary skip argument from Error, Fatal and Critical * Add stacktrace support * Fix tests * Remove x/sync from vendors? * Add stderr option to console logger * Use filepath.ToSlash to protect against Windows in tests * Remove prefixed underscores from names in colors.go * Remove not implemented database logger This was removed from Gogs on 4 Mar 2016 but left in the configuration since then. * Ensure that log paths are relative to ROOT_PATH * use path.Join * rename jsonConfig to logConfig * Rename "config" to "jsonConfig" to make it clearer * Requested changes * Requested changes: XormLogger * Try to color the windows terminal If successful default to colorizing the console logs * fixup * Colorize initially too * update vendor * Colorize logs on default and remove if this is not a colorizing logger * Fix documentation * fix test * Use go-isatty to detect if on windows we are on msys or cygwin * Fix spelling mistake * Add missing vendors * More changes * Rationalise the ANSI writer protection * Adjust colors on advice from @0x5c * Make Flags a comma separated list * Move to use the windows constant for ENABLE_VIRTUAL_TERMINAL_PROCESSING * Ensure matching is done on the non-colored message - to simpify EXPRESSION
5 years ago
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2017 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package migrations
  6. import (
  7. "fmt"
  8. "reflect"
  9. "regexp"
  10. "strings"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/setting"
  13. "xorm.io/xorm"
  14. )
  15. const minDBVersion = 70 // Gitea 1.5.3
  16. // Migration describes on migration from lower version to high version
  17. type Migration interface {
  18. Description() string
  19. Migrate(*xorm.Engine) error
  20. }
  21. type migration struct {
  22. description string
  23. migrate func(*xorm.Engine) error
  24. }
  25. // NewMigration creates a new migration
  26. func NewMigration(desc string, fn func(*xorm.Engine) error) Migration {
  27. return &migration{desc, fn}
  28. }
  29. // Description returns the migration's description
  30. func (m *migration) Description() string {
  31. return m.description
  32. }
  33. // Migrate executes the migration
  34. func (m *migration) Migrate(x *xorm.Engine) error {
  35. return m.migrate(x)
  36. }
  37. // Version describes the version table. Should have only one row with id==1
  38. type Version struct {
  39. ID int64 `xorm:"pk autoincr"`
  40. Version int64
  41. }
  42. // This is a sequence of migrations. Add new migrations to the bottom of the list.
  43. // If you want to "retire" a migration, remove it from the top of the list and
  44. // update minDBVersion accordingly
  45. var migrations = []Migration{
  46. // Gitea 1.5.3 ends at v70
  47. // v70 -> v71
  48. NewMigration("add issue_dependencies", addIssueDependencies),
  49. // v71 -> v72
  50. NewMigration("protect each scratch token", addScratchHash),
  51. // v72 -> v73
  52. NewMigration("add review", addReview),
  53. // Gitea 1.6.4 ends at v73
  54. // v73 -> v74
  55. NewMigration("add must_change_password column for users table", addMustChangePassword),
  56. // v74 -> v75
  57. NewMigration("add approval whitelists to protected branches", addApprovalWhitelistsToProtectedBranches),
  58. // v75 -> v76
  59. NewMigration("clear nonused data which not deleted when user was deleted", clearNonusedData),
  60. // Gitea 1.7.6 ends at v76
  61. // v76 -> v77
  62. NewMigration("add pull request rebase with merge commit", addPullRequestRebaseWithMerge),
  63. // v77 -> v78
  64. NewMigration("add theme to users", addUserDefaultTheme),
  65. // v78 -> v79
  66. NewMigration("rename repo is_bare to repo is_empty", renameRepoIsBareToIsEmpty),
  67. // v79 -> v80
  68. NewMigration("add can close issues via commit in any branch", addCanCloseIssuesViaCommitInAnyBranch),
  69. // v80 -> v81
  70. NewMigration("add is locked to issues", addIsLockedToIssues),
  71. // v81 -> v82
  72. NewMigration("update U2F counter type", changeU2FCounterType),
  73. // Gitea 1.8.3 ends at v82
  74. // v82 -> v83
  75. NewMigration("hot fix for wrong release sha1 on release table", fixReleaseSha1OnReleaseTable),
  76. // v83 -> v84
  77. NewMigration("add uploader id for table attachment", addUploaderIDForAttachment),
  78. // v84 -> v85
  79. NewMigration("add table to store original imported gpg keys", addGPGKeyImport),
  80. // v85 -> v86
  81. NewMigration("hash application token", hashAppToken),
  82. // v86 -> v87
  83. NewMigration("add http method to webhook", addHTTPMethodToWebhook),
  84. // v87 -> v88
  85. NewMigration("add avatar field to repository", addAvatarFieldToRepository),
  86. // Gitea 1.9.6 ends at v88
  87. // v88 -> v89
  88. NewMigration("add commit status context field to commit_status", addCommitStatusContext),
  89. // v89 -> v90
  90. NewMigration("add original author/url migration info to issues, comments, and repo ", addOriginalMigrationInfo),
  91. // v90 -> v91
  92. NewMigration("change length of some repository columns", changeSomeColumnsLengthOfRepo),
  93. // v91 -> v92
  94. NewMigration("add index on owner_id of repository and type, review_id of comment", addIndexOnRepositoryAndComment),
  95. // v92 -> v93
  96. NewMigration("remove orphaned repository index statuses", removeLingeringIndexStatus),
  97. // v93 -> v94
  98. NewMigration("add email notification enabled preference to user", addEmailNotificationEnabledToUser),
  99. // v94 -> v95
  100. NewMigration("add enable_status_check, status_check_contexts to protected_branch", addStatusCheckColumnsForProtectedBranches),
  101. // v95 -> v96
  102. NewMigration("add table columns for cross referencing issues", addCrossReferenceColumns),
  103. // v96 -> v97
  104. NewMigration("delete orphaned attachments", deleteOrphanedAttachments),
  105. // v97 -> v98
  106. NewMigration("add repo_admin_change_team_access to user", addRepoAdminChangeTeamAccessColumnForUser),
  107. // v98 -> v99
  108. NewMigration("add original author name and id on migrated release", addOriginalAuthorOnMigratedReleases),
  109. // Gitea 1.10.3 ends at v99
  110. // v99 -> v100
  111. NewMigration("add task table and status column for repository table", addTaskTable),
  112. // v100 -> v101
  113. NewMigration("update migration repositories' service type", updateMigrationServiceTypes),
  114. // v101 -> v102
  115. NewMigration("change length of some external login users columns", changeSomeColumnsLengthOfExternalLoginUser),
  116. // v102 -> v103
  117. NewMigration("update migration repositories' service type", dropColumnHeadUserNameOnPullRequest),
  118. // v103 -> v104
  119. NewMigration("Add WhitelistDeployKeys to protected branch", addWhitelistDeployKeysToBranches),
  120. // v104 -> v105
  121. NewMigration("remove unnecessary columns from label", removeLabelUneededCols),
  122. // v105 -> v106
  123. NewMigration("add includes_all_repositories to teams", addTeamIncludesAllRepositories),
  124. // v106 -> v107
  125. NewMigration("add column `mode` to table watch", addModeColumnToWatch),
  126. // v107 -> v108
  127. NewMigration("Add template options to repository", addTemplateToRepo),
  128. // v108 -> v109
  129. NewMigration("Add comment_id on table notification", addCommentIDOnNotification),
  130. // v109 -> v110
  131. NewMigration("add can_create_org_repo to team", addCanCreateOrgRepoColumnForTeam),
  132. // v110 -> v111
  133. NewMigration("change review content type to text", changeReviewContentToText),
  134. // v111 -> v112
  135. NewMigration("update branch protection for can push and whitelist enable", addBranchProtectionCanPushAndEnableWhitelist),
  136. // v112 -> v113
  137. NewMigration("remove release attachments which repository deleted", removeAttachmentMissedRepo),
  138. // v113 -> v114
  139. NewMigration("new feature: change target branch of pull requests", featureChangeTargetBranch),
  140. // v114 -> v115
  141. NewMigration("Remove authentication credentials from stored URL", sanitizeOriginalURL),
  142. // v115 -> v116
  143. NewMigration("add user_id prefix to existing user avatar name", renameExistingUserAvatarName),
  144. // v116 -> v117
  145. NewMigration("Extend TrackedTimes", extendTrackedTimes),
  146. // v117 -> v118
  147. NewMigration("Add block on rejected reviews branch protection", addBlockOnRejectedReviews),
  148. // v118 -> v119
  149. NewMigration("Add commit id and stale to reviews", addReviewCommitAndStale),
  150. // v119 -> v120
  151. NewMigration("Fix migrated repositories' git service type", fixMigratedRepositoryServiceType),
  152. // v120 -> v121
  153. NewMigration("Add owner_name on table repository", addOwnerNameOnRepository),
  154. // v121 -> v122
  155. NewMigration("add is_restricted column for users table", addIsRestricted),
  156. // v122 -> v123
  157. NewMigration("Add Require Signed Commits to ProtectedBranch", addRequireSignedCommits),
  158. // v123 -> v124
  159. NewMigration("Add original informations for reactions", addReactionOriginals),
  160. // v124 -> v125
  161. NewMigration("Add columns to user and repository", addUserRepoMissingColumns),
  162. // v125 -> v126
  163. NewMigration("Add some columns on review for migration", addReviewMigrateInfo),
  164. // v126 -> v127
  165. NewMigration("Fix topic repository count", fixTopicRepositoryCount),
  166. // v127 -> v128
  167. NewMigration("add repository code language statistics", addLanguageStats),
  168. // v128 -> v129
  169. NewMigration("fix merge base for pull requests", fixMergeBase),
  170. // v129 -> v130
  171. NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies),
  172. // v130 -> v131
  173. NewMigration("Expand webhooks for more granularity", expandWebhooks),
  174. // v131 -> v132
  175. NewMigration("Add IsSystemWebhook column to webhooks table", addSystemWebhookColumn),
  176. // v132 -> v133
  177. NewMigration("Add Branch Protection Protected Files Column", addBranchProtectionProtectedFilesColumn),
  178. // v133 -> v134
  179. NewMigration("Add EmailHash Table", addEmailHashTable),
  180. // v134 -> v135
  181. NewMigration("Refix merge base for merged pull requests", refixMergeBase),
  182. // v135 -> v136
  183. NewMigration("Add OrgID column to Labels table", addOrgIDLabelColumn),
  184. // v136 -> v137
  185. NewMigration("Add CommitsAhead and CommitsBehind Column to PullRequest Table", addCommitDivergenceToPulls),
  186. // v137 -> v138
  187. NewMigration("Add Branch Protection Block Outdated Branch", addBlockOnOutdatedBranch),
  188. // v138 -> v139
  189. NewMigration("Add ResolveDoerID to Comment table", addResolveDoerIDCommentColumn),
  190. // v139 -> v140
  191. NewMigration("prepend refs/heads/ to issue refs", prependRefsHeadsToIssueRefs),
  192. // v140 -> v141
  193. NewMigration("Save detected language file size to database instead of percent", fixLanguageStatsToSaveSize),
  194. // v141 -> v142
  195. NewMigration("Add KeepActivityPrivate to User table", addKeepActivityPrivateUserColumn),
  196. // v142 -> v143
  197. NewMigration("Ensure Repository.IsArchived is not null", setIsArchivedToFalse),
  198. // v143 -> v144
  199. NewMigration("recalculate Stars number for all user", recalculateStars),
  200. // v144 -> v145
  201. NewMigration("update Matrix Webhook http method to 'PUT'", updateMatrixWebhookHTTPMethod),
  202. // v145 -> v146
  203. NewMigration("Increase Language field to 50 in LanguageStats", increaseLanguageField),
  204. // v146 -> v147
  205. NewMigration("Add projects info to repository table", addProjectsInfo),
  206. // v147 -> v148
  207. NewMigration("create review for 0 review id code comments", createReviewsForCodeComments),
  208. // v148 -> v149
  209. NewMigration("remove issue dependency comments who refer to non existing issues", purgeInvalidDependenciesComments),
  210. // v149 -> v150
  211. NewMigration("Add Created and Updated to Milestone table", addCreatedAndUpdatedToMilestones),
  212. // v150 -> v151
  213. NewMigration("add primary key to repo_topic", addPrimaryKeyToRepoTopic),
  214. // v151 -> v152
  215. NewMigration("set default password algorithm to Argon2", setDefaultPasswordToArgon2),
  216. }
  217. // GetCurrentDBVersion returns the current db version
  218. func GetCurrentDBVersion(x *xorm.Engine) (int64, error) {
  219. if err := x.Sync(new(Version)); err != nil {
  220. return -1, fmt.Errorf("sync: %v", err)
  221. }
  222. currentVersion := &Version{ID: 1}
  223. has, err := x.Get(currentVersion)
  224. if err != nil {
  225. return -1, fmt.Errorf("get: %v", err)
  226. }
  227. if !has {
  228. return -1, nil
  229. }
  230. return currentVersion.Version, nil
  231. }
  232. // ExpectedVersion returns the expected db version
  233. func ExpectedVersion() int64 {
  234. return int64(minDBVersion + len(migrations))
  235. }
  236. // EnsureUpToDate will check if the db is at the correct version
  237. func EnsureUpToDate(x *xorm.Engine) error {
  238. currentDB, err := GetCurrentDBVersion(x)
  239. if err != nil {
  240. return err
  241. }
  242. if currentDB < 0 {
  243. return fmt.Errorf("Database has not been initialised")
  244. }
  245. if minDBVersion > currentDB {
  246. return fmt.Errorf("DB version %d (<= %d) is too old for auto-migration. Upgrade to Gitea 1.6.4 first then upgrade to this version", currentDB, minDBVersion)
  247. }
  248. expected := ExpectedVersion()
  249. if currentDB != expected {
  250. return fmt.Errorf(`Current database version %d is not equal to the expected version %d. Please run "gitea [--config /path/to/app.ini] migrate" to update the database version`, currentDB, expected)
  251. }
  252. return nil
  253. }
  254. // Migrate database to current version
  255. func Migrate(x *xorm.Engine) error {
  256. if err := x.Sync(new(Version)); err != nil {
  257. return fmt.Errorf("sync: %v", err)
  258. }
  259. currentVersion := &Version{ID: 1}
  260. has, err := x.Get(currentVersion)
  261. if err != nil {
  262. return fmt.Errorf("get: %v", err)
  263. } else if !has {
  264. // If the version record does not exist we think
  265. // it is a fresh installation and we can skip all migrations.
  266. currentVersion.ID = 0
  267. currentVersion.Version = int64(minDBVersion + len(migrations))
  268. if _, err = x.InsertOne(currentVersion); err != nil {
  269. return fmt.Errorf("insert: %v", err)
  270. }
  271. }
  272. v := currentVersion.Version
  273. if minDBVersion > v {
  274. log.Fatal(`Gitea no longer supports auto-migration from your previously installed version.
  275. Please try upgrading to a lower version first (suggested v1.6.4), then upgrade to this version.`)
  276. return nil
  277. }
  278. if int(v-minDBVersion) > len(migrations) {
  279. // User downgraded Gitea.
  280. currentVersion.Version = int64(len(migrations) + minDBVersion)
  281. _, err = x.ID(1).Update(currentVersion)
  282. return err
  283. }
  284. for i, m := range migrations[v-minDBVersion:] {
  285. log.Info("Migration[%d]: %s", v+int64(i), m.Description())
  286. if err = m.Migrate(x); err != nil {
  287. return fmt.Errorf("do migrate: %v", err)
  288. }
  289. currentVersion.Version = v + int64(i) + 1
  290. if _, err = x.ID(1).Update(currentVersion); err != nil {
  291. return err
  292. }
  293. }
  294. return nil
  295. }
  296. // RecreateTables will recreate the tables for the provided beans using the newly provided bean definition and move all data to that new table
  297. // WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION
  298. func RecreateTables(beans ...interface{}) func(*xorm.Engine) error {
  299. return func(x *xorm.Engine) error {
  300. sess := x.NewSession()
  301. defer sess.Close()
  302. if err := sess.Begin(); err != nil {
  303. return err
  304. }
  305. sess = sess.StoreEngine("InnoDB")
  306. for _, bean := range beans {
  307. log.Info("Recreating Table: %s for Bean: %s", x.TableName(bean), reflect.Indirect(reflect.ValueOf(bean)).Type().Name())
  308. if err := recreateTable(sess, bean); err != nil {
  309. return err
  310. }
  311. }
  312. return sess.Commit()
  313. }
  314. }
  315. // recreateTable will recreate the table using the newly provided bean definition and move all data to that new table
  316. // WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION
  317. // WARNING: YOU MUST COMMIT THE SESSION AT THE END
  318. func recreateTable(sess *xorm.Session, bean interface{}) error {
  319. // TODO: This will not work if there are foreign keys
  320. tableName := sess.Engine().TableName(bean)
  321. tempTableName := fmt.Sprintf("tmp_recreate__%s", tableName)
  322. // We need to move the old table away and create a new one with the correct columns
  323. // We will need to do this in stages to prevent data loss
  324. //
  325. // First create the temporary table
  326. if err := sess.Table(tempTableName).CreateTable(bean); err != nil {
  327. log.Error("Unable to create table %s. Error: %v", tempTableName, err)
  328. return err
  329. }
  330. if err := sess.Table(tempTableName).CreateUniques(bean); err != nil {
  331. log.Error("Unable to create uniques for table %s. Error: %v", tempTableName, err)
  332. return err
  333. }
  334. if err := sess.Table(tempTableName).CreateIndexes(bean); err != nil {
  335. log.Error("Unable to create indexes for table %s. Error: %v", tempTableName, err)
  336. return err
  337. }
  338. // Work out the column names from the bean - these are the columns to select from the old table and install into the new table
  339. table, err := sess.Engine().TableInfo(bean)
  340. if err != nil {
  341. log.Error("Unable to get table info. Error: %v", err)
  342. return err
  343. }
  344. newTableColumns := table.Columns()
  345. if len(newTableColumns) == 0 {
  346. return fmt.Errorf("no columns in new table")
  347. }
  348. hasID := false
  349. for _, column := range newTableColumns {
  350. hasID = hasID || (column.IsPrimaryKey && column.IsAutoIncrement)
  351. }
  352. if hasID && setting.Database.UseMSSQL {
  353. if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` ON", tempTableName)); err != nil {
  354. log.Error("Unable to set identity insert for table %s. Error: %v", tempTableName, err)
  355. return err
  356. }
  357. }
  358. sqlStringBuilder := &strings.Builder{}
  359. _, _ = sqlStringBuilder.WriteString("INSERT INTO `")
  360. _, _ = sqlStringBuilder.WriteString(tempTableName)
  361. _, _ = sqlStringBuilder.WriteString("` (`")
  362. _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name)
  363. _, _ = sqlStringBuilder.WriteString("`")
  364. for _, column := range newTableColumns[1:] {
  365. _, _ = sqlStringBuilder.WriteString(", `")
  366. _, _ = sqlStringBuilder.WriteString(column.Name)
  367. _, _ = sqlStringBuilder.WriteString("`")
  368. }
  369. _, _ = sqlStringBuilder.WriteString(")")
  370. _, _ = sqlStringBuilder.WriteString(" SELECT ")
  371. if newTableColumns[0].Default != "" {
  372. _, _ = sqlStringBuilder.WriteString("COALESCE(`")
  373. _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name)
  374. _, _ = sqlStringBuilder.WriteString("`, ")
  375. _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Default)
  376. _, _ = sqlStringBuilder.WriteString(")")
  377. } else {
  378. _, _ = sqlStringBuilder.WriteString("`")
  379. _, _ = sqlStringBuilder.WriteString(newTableColumns[0].Name)
  380. _, _ = sqlStringBuilder.WriteString("`")
  381. }
  382. for _, column := range newTableColumns[1:] {
  383. if column.Default != "" {
  384. _, _ = sqlStringBuilder.WriteString(", COALESCE(`")
  385. _, _ = sqlStringBuilder.WriteString(column.Name)
  386. _, _ = sqlStringBuilder.WriteString("`, ")
  387. _, _ = sqlStringBuilder.WriteString(column.Default)
  388. _, _ = sqlStringBuilder.WriteString(")")
  389. } else {
  390. _, _ = sqlStringBuilder.WriteString(", `")
  391. _, _ = sqlStringBuilder.WriteString(column.Name)
  392. _, _ = sqlStringBuilder.WriteString("`")
  393. }
  394. }
  395. _, _ = sqlStringBuilder.WriteString(" FROM `")
  396. _, _ = sqlStringBuilder.WriteString(tableName)
  397. _, _ = sqlStringBuilder.WriteString("`")
  398. if _, err := sess.Exec(sqlStringBuilder.String()); err != nil {
  399. log.Error("Unable to set copy data in to temp table %s. Error: %v", tempTableName, err)
  400. return err
  401. }
  402. if hasID && setting.Database.UseMSSQL {
  403. if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` OFF", tempTableName)); err != nil {
  404. log.Error("Unable to switch off identity insert for table %s. Error: %v", tempTableName, err)
  405. return err
  406. }
  407. }
  408. switch {
  409. case setting.Database.UseSQLite3:
  410. // SQLite will drop all the constraints on the old table
  411. if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
  412. log.Error("Unable to drop old table %s. Error: %v", tableName, err)
  413. return err
  414. }
  415. if err := sess.Table(tempTableName).DropIndexes(bean); err != nil {
  416. log.Error("Unable to drop indexes on temporary table %s. Error: %v", tempTableName, err)
  417. return err
  418. }
  419. if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil {
  420. log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err)
  421. return err
  422. }
  423. if err := sess.Table(tableName).CreateIndexes(bean); err != nil {
  424. log.Error("Unable to recreate indexes on table %s. Error: %v", tableName, err)
  425. return err
  426. }
  427. if err := sess.Table(tableName).CreateUniques(bean); err != nil {
  428. log.Error("Unable to recreate uniques on table %s. Error: %v", tableName, err)
  429. return err
  430. }
  431. case setting.Database.UseMySQL:
  432. // MySQL will drop all the constraints on the old table
  433. if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
  434. log.Error("Unable to drop old table %s. Error: %v", tableName, err)
  435. return err
  436. }
  437. // SQLite and MySQL will move all the constraints from the temporary table to the new table
  438. if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil {
  439. log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err)
  440. return err
  441. }
  442. case setting.Database.UsePostgreSQL:
  443. // CASCADE causes postgres to drop all the constraints on the old table
  444. if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s` CASCADE", tableName)); err != nil {
  445. log.Error("Unable to drop old table %s. Error: %v", tableName, err)
  446. return err
  447. }
  448. // CASCADE causes postgres to move all the constraints from the temporary table to the new table
  449. if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` RENAME TO `%s`", tempTableName, tableName)); err != nil {
  450. log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err)
  451. return err
  452. }
  453. var indices []string
  454. schema := sess.Engine().Dialect().URI().Schema
  455. sess.Engine().SetSchema("")
  456. if err := sess.Table("pg_indexes").Cols("indexname").Where("tablename = ? ", tableName).Find(&indices); err != nil {
  457. log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err)
  458. return err
  459. }
  460. sess.Engine().SetSchema(schema)
  461. for _, index := range indices {
  462. newIndexName := strings.Replace(index, "tmp_recreate__", "", 1)
  463. if _, err := sess.Exec(fmt.Sprintf("ALTER INDEX `%s` RENAME TO `%s`", index, newIndexName)); err != nil {
  464. log.Error("Unable to rename %s to %s. Error: %v", index, newIndexName, err)
  465. return err
  466. }
  467. }
  468. case setting.Database.UseMSSQL:
  469. // MSSQL will drop all the constraints on the old table
  470. if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
  471. log.Error("Unable to drop old table %s. Error: %v", tableName, err)
  472. return err
  473. }
  474. // MSSQL sp_rename will move all the constraints from the temporary table to the new table
  475. if _, err := sess.Exec(fmt.Sprintf("sp_rename `%s`,`%s`", tempTableName, tableName)); err != nil {
  476. log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err)
  477. return err
  478. }
  479. default:
  480. log.Fatal("Unrecognized DB")
  481. }
  482. return nil
  483. }
  484. // WARNING: YOU MUST COMMIT THE SESSION AT THE END
  485. func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...string) (err error) {
  486. if tableName == "" || len(columnNames) == 0 {
  487. return nil
  488. }
  489. // TODO: This will not work if there are foreign keys
  490. switch {
  491. case setting.Database.UseSQLite3:
  492. // First drop the indexes on the columns
  493. res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName))
  494. if errIndex != nil {
  495. return errIndex
  496. }
  497. for _, row := range res {
  498. indexName := row["name"]
  499. indexRes, err := sess.Query(fmt.Sprintf("PRAGMA index_info(`%s`)", indexName))
  500. if err != nil {
  501. return err
  502. }
  503. if len(indexRes) != 1 {
  504. continue
  505. }
  506. indexColumn := string(indexRes[0]["name"])
  507. for _, name := range columnNames {
  508. if name == indexColumn {
  509. _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s`", indexName))
  510. if err != nil {
  511. return err
  512. }
  513. }
  514. }
  515. }
  516. // Here we need to get the columns from the original table
  517. sql := fmt.Sprintf("SELECT sql FROM sqlite_master WHERE tbl_name='%s' and type='table'", tableName)
  518. res, err := sess.Query(sql)
  519. if err != nil {
  520. return err
  521. }
  522. tableSQL := string(res[0]["sql"])
  523. // Separate out the column definitions
  524. tableSQL = tableSQL[strings.Index(tableSQL, "("):]
  525. // Remove the required columnNames
  526. for _, name := range columnNames {
  527. tableSQL = regexp.MustCompile(regexp.QuoteMeta("`"+name+"`")+"[^`,)]*?[,)]").ReplaceAllString(tableSQL, "")
  528. }
  529. // Ensure the query is ended properly
  530. tableSQL = strings.TrimSpace(tableSQL)
  531. if tableSQL[len(tableSQL)-1] != ')' {
  532. if tableSQL[len(tableSQL)-1] == ',' {
  533. tableSQL = tableSQL[:len(tableSQL)-1]
  534. }
  535. tableSQL += ")"
  536. }
  537. // Find all the columns in the table
  538. columns := regexp.MustCompile("`([^`]*)`").FindAllString(tableSQL, -1)
  539. tableSQL = fmt.Sprintf("CREATE TABLE `new_%s_new` ", tableName) + tableSQL
  540. if _, err := sess.Exec(tableSQL); err != nil {
  541. return err
  542. }
  543. // Now restore the data
  544. columnsSeparated := strings.Join(columns, ",")
  545. insertSQL := fmt.Sprintf("INSERT INTO `new_%s_new` (%s) SELECT %s FROM %s", tableName, columnsSeparated, columnsSeparated, tableName)
  546. if _, err := sess.Exec(insertSQL); err != nil {
  547. return err
  548. }
  549. // Now drop the old table
  550. if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
  551. return err
  552. }
  553. // Rename the table
  554. if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `new_%s_new` RENAME TO `%s`", tableName, tableName)); err != nil {
  555. return err
  556. }
  557. case setting.Database.UsePostgreSQL:
  558. cols := ""
  559. for _, col := range columnNames {
  560. if cols != "" {
  561. cols += ", "
  562. }
  563. cols += "DROP COLUMN `" + col + "` CASCADE"
  564. }
  565. if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
  566. return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
  567. }
  568. case setting.Database.UseMySQL:
  569. // Drop indexes on columns first
  570. sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','"))
  571. res, err := sess.Query(sql)
  572. if err != nil {
  573. return err
  574. }
  575. for _, index := range res {
  576. indexName := index["column_name"]
  577. if len(indexName) > 0 {
  578. _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s` ON `%s`", indexName, tableName))
  579. if err != nil {
  580. return err
  581. }
  582. }
  583. }
  584. // Now drop the columns
  585. cols := ""
  586. for _, col := range columnNames {
  587. if cols != "" {
  588. cols += ", "
  589. }
  590. cols += "DROP COLUMN `" + col + "`"
  591. }
  592. if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
  593. return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
  594. }
  595. case setting.Database.UseMSSQL:
  596. cols := ""
  597. for _, col := range columnNames {
  598. if cols != "" {
  599. cols += ", "
  600. }
  601. cols += "`" + strings.ToLower(col) + "`"
  602. }
  603. sql := fmt.Sprintf("SELECT Name FROM SYS.DEFAULT_CONSTRAINTS WHERE PARENT_OBJECT_ID = OBJECT_ID('%[1]s') AND PARENT_COLUMN_ID IN (SELECT column_id FROM sys.columns WHERE lower(NAME) IN (%[2]s) AND object_id = OBJECT_ID('%[1]s'))",
  604. tableName, strings.Replace(cols, "`", "'", -1))
  605. constraints := make([]string, 0)
  606. if err := sess.SQL(sql).Find(&constraints); err != nil {
  607. return fmt.Errorf("Find constraints: %v", err)
  608. }
  609. for _, constraint := range constraints {
  610. if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` DROP CONSTRAINT `%s`", tableName, constraint)); err != nil {
  611. return fmt.Errorf("Drop table `%s` constraint `%s`: %v", tableName, constraint, err)
  612. }
  613. }
  614. if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` DROP COLUMN %s", tableName, cols)); err != nil {
  615. return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
  616. }
  617. default:
  618. log.Fatal("Unrecognized DB")
  619. }
  620. return nil
  621. }