summaryrefslogtreecommitdiff
path: root/lib/api
Commit message (Collapse)AuthorAgeFilesLines
* Merge branch 'ee-581-backport-changes' into 'master' Douwe Maan2016-08-172-14/+21
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Backport changes from gitlab-org/gitlab-ee!581 ## What does this MR do? Backports changes that were made in gitlab-org/gitlab-ee!581, to avoid potential merge conflicts in the future. ## What are the relevant issue numbers? - Related to gitlab-org/gitlab-ee!581 ## Does this MR meet the acceptance criteria? ## Tasks - [ ] !5824 Backport changes from EE!581 to CE - [x] Implementation - [x] ::ProtectedBranches::CreateService.new - [x] Can't remove `load_protected_branches_gon_variables` - [x] `has_many` with count enforced - [x] Extract from access levels - [x] project.protected_branches.create(params) - [x] Improve "access_levels.first" - [x] Fix tests - [x] Fix build - [x] Assign to Douwe - [ ] Wait for review/merge See merge request !5824
* Refactored AkismetHelper into AkismetService and cleaned up `Spammable`Patricio Cano2016-08-151-2/+0
| | | | - Refactored SpamCheckService into SpamService
* Refactored spam related code even furtherPatricio Cano2016-08-151-1/+1
| | | | | | | - Removed unnecessary column from `SpamLog` - Moved creation of SpamLogs out of its own service and into SpamCheckService - Simplified code in SpamCheckService. - Moved move spam related code into Spammable concern
* Complete refactor of the `Spammable` concern and tests:Patricio Cano2016-08-151-1/+1
| | | | | | | - Merged `AkismetSubmittable` into `Spammable` - Clean up `SpamCheckService` - Added tests for `Spammable` - Added submit (ham or spam) options to `AkismetHelper`
* Recover usage of Todos counter cache20842-todos-queries-cachePaco Guzman2016-08-121-4/+2
| | | | | | | We’re being kept up to date the counter data but we’re not using it. The only thing which is not real if is the number of projects that the user read changes the number of todos can be stale for some time. The counters will be sync just after the user receives a new todo or mark any as done
* Use cache for todos counter calling TodoServicePaco Guzman2016-08-121-1/+1
|
* api for generating new merge requestScott Le2016-08-111-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | DRY code + fix rubocop Add more test cases Append to changelog DRY changes list find_url service for merge_requests use GET for getting merge request links remove files rename to get_url_service reduce loop add test case for cross project refactor tiny thing update changelog
* Improve the performance of the GET /:sources/:id/{access_requests,members} ↵Rémy Coutable2016-08-103-8/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | API endpoints The performance was greatly improved by removing two N+1 queries issues for each endpoint. For comparison: 1. `GET /projects/:id/members` With two N+1 queries issues (one was already fxed in the following snippet): ``` ProjectMember Load (0.2ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND "members"."requested_at" IS NULL ORDER BY "members"."id" DESC [["source_type", "Project"], ["source_id", 1], ["source_type", "Project"]] User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (5, 22, 16, 13) ORDER BY "users"."id" DESC ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations" ProjectMember Load (0.3ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND "members"."requested_at" IS NULL AND "members"."user_id" = $4 ORDER BY "members"."id" DESC LIMIT 1 [["source_type", "Project"], ["source_id", 1], ["source_type", "Project"], ["user_id", 5]] ProjectMember Load (0.3ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND "members"."requested_at" IS NULL AND "members"."user_id" = $4 ORDER BY "members"."id" DESC LIMIT 1 [["source_type", "Project"], ["source_id", 1], ["source_type", "Project"], ["user_id", 22]] ProjectMember Load (0.3ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND "members"."requested_at" IS NULL AND "members"."user_id" = $4 ORDER BY "members"."id" DESC LIMIT 1 [["source_type", "Project"], ["source_id", 1], ["source_type", "Project"], ["user_id", 16]] ProjectMember Load (0.3ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND "members"."requested_at" IS NULL AND "members"."user_id" = $4 ORDER BY "members"."id" DESC LIMIT 1 [["source_type", "Project"], ["source_id", 1], ["source_type", "Project"], ["user_id", 13]] ``` Without the N+1 queries issues: ``` ProjectMember Load (0.3ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND "members"."requested_at" IS NULL ORDER BY "members"."id" DESC LIMIT 20 OFFSET 0 [["source_type", "Project"], ["source_id", 1], ["source_type", "Project"]] User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (5, 22, 16, 13) ORDER BY "users"."id" DESC ``` 2. `GET /projects/:id/access_requests` With two N+1 queries issues: ``` ProjectMember Load (0.3ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND ("members"."requested_at" IS NOT NULL) ORDER BY "members"."id" DESC [["source_type", "Project"], ["source_id", 8], ["source_type", "Project"]] User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" DESC LIMIT 1 [["id", 24]] User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" DESC LIMIT 1 [["id", 23]] ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations" ProjectMember Load (0.1ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND ("members"."requested_at" IS NOT NULL) AND "members"."user_id" = $4 ORDER BY "members"."id" DESC LIMIT 1 [["source_type", "Project"], ["source_id", 8], ["source_type", "Project"], ["user_id", 24]] ProjectMember Load (0.2ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND ("members"."requested_at" IS NOT NULL) AND "members"."user_id" = $4 ORDER BY "members"."id" DESC LIMIT 1 [["source_type", "Project"], ["source_id", 8], ["source_type", "Project"], ["user_id", 23]] ``` Without the N+1 queries issues: ``` ProjectMember Load (0.3ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = $1 AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $2 AND "members"."source_type" = $3 AND "members"."type" IN ('ProjectMember') AND ("members"."requested_at" IS NOT NULL) ORDER BY "members"."id" DESC LIMIT 20 OFFSET 0 [["source_type", "Project"], ["source_id", 8], ["source_type", "Project"]] User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (24, 23) ORDER BY "users"."id" DESC ``` Signed-off-by: Rémy Coutable <remy@rymai.me>
* Restore back-compatibility for current members API endpointsRémy Coutable2016-08-102-8/+38
| | | | Signed-off-by: Rémy Coutable <remy@rymai.me>
* New AccessRequests API endpoints for Group & ProjectRémy Coutable2016-08-108-229/+253
| | | | | | | | Also, mutualize AccessRequests and Members endpoints for Group & Project. New API documentation for the AccessRequests endpoints. Signed-off-by: Rémy Coutable <remy@rymai.me>
* Clean up project destructionclean-up-project-destroyStan Hu2016-08-101-1/+1
| | | | | | Instead of redirecting from the project service to the service and back to the model, put all destruction code in the service. Also removes a possible source of failure where run_after_commit may not destroy the project.
* Retain old behaviorConnor Shea2016-08-091-2/+4
|
* Merge branch 'zj-enable-deploy-keys-api' into 'master' Douwe Maan2016-08-081-38/+66
|\ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Enable/Disable Deploy keys for a project Closes #20123 ## Does this MR meet the acceptance criteria? - [X] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added - [X] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md) - [X] API support added - Tests - [X] Added for this feature/bug - [X] All builds are passing See merge request !5647
| * Namespace EnableDeployKeyService under ProjectsZ.J. van de Weg2016-08-081-1/+2
| |
| * Create service for enabling deploy keysZ.J. van de Weg2016-08-051-3/+3
| |
| * Move deploy_key tests to deploy_key_spec.rbZ.J. van de Weg2016-08-041-5/+6
| | | | | | | | Also, fix the failing test in the process
| * Use Grape DSL for deploy keys endpointsZ.J. van de Weg2016-08-031-39/+34
| | | | | | | | Also a minor clean up of the post endpoint
| * Endpoints to enable and disable deploy keysZ.J. van de Weg2016-08-031-0/+31
| | | | | | | | Resolves #20123
* | switch from diff_file_collection to diffs20034-safe-diffsPaco Guzman2016-08-032-3/+3
|/ | | | So we have raw_diffs too
* Minor fixes in the Env API endpointszj-env-external-urlZ.J. van de Weg2016-08-011-1/+5
|
* Use Grape DSL for environment endpointsZ.J. van de Weg2016-07-292-48/+47
| | | | Also a couple of minor edits for this branch are included
* Incorporate feedbackZ.J. van de Weg2016-07-291-4/+1
|
* Add API support for environmentsZ.J. van de Weg2016-07-293-0/+92
|
* Use `Gitlab::Access` to protected branch access levels.Timothy Andrew2016-07-292-11/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | 1. It makes sense to reuse these constants since we had them duplicated in the previous enum implementation. This also simplifies our `check_access` implementation, because we can use `project.team.max_member_access` directly. 2. Use `accepts_nested_attributes_for` to create push/merge access levels. This was a bit fiddly to set up, but this simplifies our code by quite a large amount. We can even get rid of `ProtectedBranches::BaseService`. 3. Move API handling back into the API (previously in `ProtectedBranches::BaseService#translate_api_params`. 4. The protected branch services now return a `ProtectedBranch` rather than `true/false`. 5. Run `load_protected_branches` on-demand in the `create` action, to prevent it being called unneccessarily. 6. "Masters" is pre-selected as the default option for "Allowed to Push" and "Allowed to Merge". 7. These changes were based on a review from @rymai in !5081.
* Have the `branches` API work with the new protected branches data model.Timothy Andrew2016-07-292-14/+21
| | | | | | | | | | | | 1. The new data model moves from `developers_can_{push,merge}` to `allowed_to_{push,merge}`. 2. The API interface has not been changed. It still accepts `developers_can_push` and `developers_can_merge` as options. These attributes are inferred from the new data model. 3. Modify the protected branch create/update services to translate from the API interface to our current data model.
* Add commit stats to commit api responsedixpac2016-07-281-0/+5
|
* Refactor spam validation to a concern that can be easily reused and improve ↵akismet-ui-checkPatricio Cano2016-07-261-7/+5
| | | | legibility in `SpamCheckService`
* Refactor `SpamCheckService` to make it cleaner and clearer.Patricio Cano2016-07-261-4/+6
|
* Submit all issues on public projects to Akismet if enabled.Patricio Cano2016-07-261-5/+3
|
* Submit new issues created via the WebUI by non project members to Akismet ↵Patricio Cano2016-07-261-12/+1
| | | | for spam check.
* Merge branch 'artifacts-from-ref-and-build-name-api' into 'master' Rémy Coutable2016-07-221-1/+1
|\ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Simpler two queries than one JOIN with subquery This is a follow up from !5347 Originally it was: ``` ruby pipeline = pipelines.latest_successful_for(ref) builds.where(pipeline: pipeline).latest.with_artifacts ``` However MySQL would complain that we can't use `IN` against a subquery which has `LIMIT`. Using `INNER JOIN` would be a workaround, however, doing that is too complicated in current version of Rails. So let's just use two queries in this case. Closes #14419 See merge request !5388
| * Also fix the URL in the commentartifacts-from-ref-and-build-name-apiLin Jen-Shin2016-07-211-1/+1
| |
* | Merge branch 'artifacts-from-ref-and-build-name-api' into 'master' Rémy Coutable2016-07-211-20/+38
|\ \ | |/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | API for downloading latest successful build ## What does this MR do? Implement parts of #4255, particularly the API. ## Are there points in the code the reviewer needs to double check? I still made it that `ref` could be either branch, tag, or even SHA with: ``` ruby # ref can't be HEAD, can only be branch/tag name or SHA scope :latest_successful_for, ->(ref) do table = quoted_table_name # TODO: Use `where(ref: ref).or(sha: ref)` in Rails 5 where("#{table}.ref = ? OR #{table}.sha = ?", ref, ref). success.order(id: :desc) end ``` Because the reasons I put in: * https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13165543 * https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13165921 But if you still think that it's not good to do it this way, I'll drop it and let's think about the other way to satisfy the requirement specified in https://gitlab.com/gitlab-org/gitlab-ce/issues/4255#note_13101233 It could be `status=any` or `sha=DEADBEAF` ## What are the relevant issue numbers? Part of #4255 ## Does this MR meet the acceptance criteria? - [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added - [ ] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md) - [x] API support added - Tests - [x] Added for this feature/bug - [ ] All builds are passing - [ ] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides) - [ ] Branch has no merge conflicts with `master` (if you do - rebase it please) - [ ] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) See merge request !5347
| * Merge branch 'master' into artifacts-from-ref-and-build-name-apiLin Jen-Shin2016-07-214-8/+4
| |\ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * master: (261 commits) Add link to user profile to commit avatar (!5163) Refactor service settings view Fix a problem with processing a pipeline where stage only has manual actions A CHANGELOG entry Don't show other actions of the same name Use limit parameter rather than hardcoded value Remove icons from explore nav Change how we style redirect_to Use flash[:notice] only Create PipelinesSettingsController for showing settings page Fix a few nitpicks Allow to disable user request access to groups/projects Enable Style/MultilineTernaryOperator rubocop cop Fix review comments Update routes Update CHANGELOG Improve implementation of variables Log cron_jobs configuration instead of raising exception Added checks for migration downtime Ensure to_json methods take optional argument ...
| * | Should check against `authorize_read_builds!`Lin Jen-Shin2016-07-201-0/+2
| | |
| * | Artifacts are plural, feedback:Lin Jen-Shin2016-07-201-3/+3
| | | | | | | | | | | | https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5347/diffs#note_13173284
| * | Merge branch 'master' into artifacts-from-ref-and-build-name-apiLin Jen-Shin2016-07-193-43/+22
| |\ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * master: (23 commits) Add CHANGELOG entry [ci skip] CHANGELOG item Added redirect_to_referer to login link on issues Simplify entities for branches and tags API Added Rake task for tracking deployments Return the number of marked todos Use local_assigns Use `humanize` Improve code design Remove unused create_pipeline_service_spec.rb Add notice implementation Make manual actions to work with master code Use `capitalize` instead of `titleize` for manual actions Mark builds with manual actions as skipped Fix rubocop offenses Update build fixtures to include manual actions Improve manual actions code and add model, service and feature tests Rename playable_actions to manual_actions Add implementation of manual actions Position commit icons closer to branch name/tag/sha; add min-width to pipeline actions cell ...
| * | | API for downloading latest successful build:Lin Jen-Shin2016-07-191-21/+37
| | | | | | | | | | | | | | | | | | | | | | | | This was extracted from !5142 and implementing part of #4255. We split it from !5142 because we want to ship it in 8.10 while !5142 was not ready yet.
* | | | Merge branch 'email-domain-blacklist' into 'master' Robert Speicher2016-07-201-1/+3
|\ \ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Added the ability to block sign ups using a domain blacklist. As part of this MR, I restructured the Application Settings form to separate **Sign up** related settings from **Sign in** related settings and make everything cleaner and easier to read. Fixes #19749 Related to #5573 See merge request !5259
| * | | | Refactor and rename `restricted_signup_domains` to `domain_whitelist` to ↵Patricio Cano2016-07-181-1/+1
| | | | | | | | | | | | | | | | | | | | better conform to its behavior and newly introduced behavior.
| * | | | Added the ability to block sign ups using a domain blacklist.Patricio Cano2016-07-181-0/+2
| | | | |
* | | | | Change `return`s for `next`s to please rubocop (behaviour is the same)Alejandro Rodríguez2016-07-201-2/+2
| | | | |
* | | | | Add /deploy_keys API to retrieve all deploy keys regardless of project ↵Alejandro Rodríguez2016-07-201-53/+66
| |_|_|/ |/| | | | | | | | | | | | | | | | | | | | | | | affiliation Also, in favour of consistency, deprecate `/projects/:id/keys/...` routes in favour of `/projects/:id/deploy_keys/...`
* | | | Merge branch 'remove-parse-boolean' into 'master' Rémy Coutable2016-07-204-8/+4
|\ \ \ \ | |_|_|/ |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Replace parse_boolean with to_boolean ## What does this MR do? Replaces `.parse_boolean` with the new `.to_boolean` as we talked in the other MR. ## Does this MR meet the acceptance criteria? ~~- [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added~~ ~~- [x] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)~~ ~~- [ ] API support added~~ - Tests ~~- [ ] Added for this feature/bug~~ - [x] All builds are passing - [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides) - [x] Branch has no merge conflicts with `master` (if you do - rebase it please) - [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) See merge request !5355
| * | | Replace parse_boolean with to_booleanRobert Schilling2016-07-204-8/+4
| | |/ | |/|
* | | Merge branch 'api-cleanup-entities' into 'master' Rémy Coutable2016-07-192-42/+21
|\ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Simplify entities for branches and tags API ## What does this MR do? As talked in !5208, I improved the entity for branches and tags. ## Does this MR meet the acceptance criteria? ~~- [ ] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added~~ ~~- [ ] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)~~ ~~- [ ] API support added~~ ~~- Tests~~ ~~- [ ] Added for this feature/bug~~ ~~- [ ] All builds are passing~~ ~~- [ ] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)~~ ~~- [ ] Branch has no merge conflicts with `master` (if you do - rebase it please)~~ ~~- [ ] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)~~ See merge request !5343
| * | | Simplify entities for branches and tags APIapi-cleanup-entitiesRobert Schilling2016-07-192-42/+21
| |/ /
* | | Merge branch 'api-delete-todos' into 'master' Rémy Coutable2016-07-191-1/+1
|\ \ \ | |/ / |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Api delete todos ## What does this MR do? It changes the `DELETE /todos` to only return the number of marked todos. ## Why was this MR needed? Before it returned the marked todos as an paginated array. Since we deleted/marked the todos, there was no way to get the rest of the todos. ## What are the relevant issue numbers? Closes #19678 ## Does this MR meet the acceptance criteria? ~~- [x] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added~~ - [x] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md) - [x] API support added - Tests - [x] Added for this feature/bug - [x] All builds are passing - [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides) - [x] Branch has no merge conflicts with `master` (if you do - rebase it please) - [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) See merge request !5341
| * | Return the number of marked todosapi-delete-todosRobert Schilling2016-07-191-1/+1
| | |
* | | Only update onceRobert Schilling2016-07-191-2/+3
| | |