SuccessConsole Output

Skipping 582 KB.. Full Log
ver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo4 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Supplying the add parameter without a remote url issues a 500 status code # RemoteManagement.feature:124
    Given There is a default multirepo server with remotes                            # WebAPICucumberHooks.setUpDefaultMultiRepoWithRemotes()
    When I call "GET /repos/repo3/remote?add=true&remoteName=newRemote"               # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                          # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "No URL was specified."             # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo3 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo4 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Supplying add with valid parameters adds a new remote                        # RemoteManagement.feature:130
    Given There is a default multirepo server with remotes                               # WebAPICucumberHooks.setUpDefaultMultiRepoWithRemotes()
    When I call "GET /repos/repo3/remote?add=true&remoteName=newRemote&remoteURL=newUrl" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                             # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/name/text()" equals "newRemote"                             # WebAPICucumberHooks.checkXPathEquals(String,String)
    When I call "GET /repos/repo3/remote?list=true"                                      # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                             # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Remote" 3 times                       # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the response body should contain "repo1"                                         # WebAPICucumberHooks.checkResponseTextContains(String)
    And the response body should contain "repo2"                                         # WebAPICucumberHooks.checkResponseTextContains(String)
    And the response body should contain "newRemote"                                     # WebAPICucumberHooks.checkResponseTextContains(String)
@Commands @Remove
Feature: Remove
  The remove command allows a user to remove features from the repository and is supported through the "/repos/{repository}/remove" endpoint
  The command must be executed using the HTTP GET method
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method issues 405 "Method not allowed" # Remove.feature:6
    Given There is an empty repository named repo1                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/remove"                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                 # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Removing outside of a transaction issues 500 "Transaction required"    # Remove.feature:12
    Given There is an empty repository named repo1                                 # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/remove?path=somePath"                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                       # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "No transaction was specified" # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Removing outside of a repository issues 404 "Not found" # Remove.feature:18
    Given There is an empty multirepo server                        # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/remove?path=somePath"             # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                        # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"             # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"     # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Removing with no path issues a 500 status code                                      # Remove.feature:25
    Given There is an empty repository named repo1                                              # WebAPICucumberHooks.setUpEmptyRepo(String)
    And I have a transaction as "@txId" on the "repo1" repo                                     # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/remove?transactionId={@txId}"                                 # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                    # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "Required parameter 'path' was not provided." # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Removing with a feature path removes the specified feature                                   # Remove.feature:32
    Given There is a default multirepo server                                                            # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I have a transaction as "@txId" on the "repo1" repo                                              # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And the repo1 repository's "STAGE_HEAD" in the @txId transaction should have the following features: # WebAPICucumberHooks.verifyRepositoryContentsTx(String,String,String,DataTable)
    When I call "GET /repos/repo1/remove?path=Points/Point.1&transactionId={@txId}"                      # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                             # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Deleted/text()" equals "Points/Point.1"                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the repo1 repository's "STAGE_HEAD" in the @txId transaction should have the following features: # WebAPICucumberHooks.verifyRepositoryContentsTx(String,String,String,DataTable)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Removing with a tree path and no recursive parameter issues a 400 status code                               # Remove.feature:50
    Given There is a default multirepo server                                                                           # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I have a transaction as "@txId" on the "repo1" repo                                                             # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/remove?path=Points&transactionId={@txId}"                                             # WebAPICucumberHooks.callURL(String)
    Then the response status should be '400'                                                                            # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "Cannot remove tree Points if recursive or truncate is not specified" # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Removing with a tree path and the recursive parameter removes the specified feature tree     # Remove.feature:57
    Given There is a default multirepo server                                                            # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I have a transaction as "@txId" on the "repo1" repo                                              # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And the repo1 repository's "STAGE_HEAD" in the @txId transaction should have the following features: # WebAPICucumberHooks.verifyRepositoryContentsTx(String,String,String,DataTable)
    When I call "GET /repos/repo1/remove?path=Points&recursive=true&transactionId={@txId}"               # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                             # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Deleted/text()" equals "Points"                                             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the repo1 repository's "STAGE_HEAD" in the @txId transaction should have the following features: # WebAPICucumberHooks.verifyRepositoryContentsTx(String,String,String,DataTable)
@RepositoryManagement @RenameRepository
Feature: Rename repository
  Repositories being served throught the Web API are served through the "/repos/<repository name>" entry point.
  The name of a repository is unique across a Web API instance.
  Renaming a repository is done through a "POST /repos/<repository name>/rename?name={new name}" call.
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository nonExistingRepo using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling rename to a non existing repo issues 404 "Not Found" # RenameRepository.feature:7
    Given There is an empty multirepo server                             # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "POST /repos/nonExistingRepo/rename?name=renamedRepo"    # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                             # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"                  # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"          # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling rename on a repo using the wrong HTTP method issues 405 "Method not allowed" # RenameRepository.feature:14
    Given There is a default multirepo server                                                    # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "GET /repos/repo1/rename?name=renamedRepo"                                       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "POST"                                            # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Trying to assign a duplicated name to a repo issues 400 "Bad request"               # RenameRepository.feature:20
    Given There is a default multirepo server                                                   # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "POST /repos/repo1/rename?name=repo2"                                           # WebAPICucumberHooks.callURL(String)
    Then the response status should be '400'                                                    # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "application/xml"                                    # WebAPICucumberHooks.checkContentType(String)
    And the xpath "/response/success/text()" equals "false"                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/error/text()" equals "A repository with that name already exists." # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Renaming a repository returns a link to the new location issues 301 "Moved permanently" # RenameRepository.feature:28
    Given There is a default multirepo server                                                       # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "POST /repos/repo1/rename?name=repo1Renamed"                                        # WebAPICucumberHooks.callURL(String)
    Then the response status should be '301'                                                        # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "application/xml"                                        # WebAPICucumberHooks.checkContentType(String)
    And the xpath "/response/success/text()" equals "true"                                          # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/repo/name/text()" equals "repo1Renamed"                                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/repo/atom:link/@href" contains "/repos/repo1Renamed.xml"               # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository nonExistingRepo using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling rename to a non existing repo issues 404 "Not Found", JSON requested response # RenameRepository.feature:37
    Given There is an empty multirepo server                                                      # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "POST /repos/nonExistingRepo/rename.json?name=renamedRepo"                        # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                                                      # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"                                           # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"                                   # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling rename on a repo using the wrong HTTP method issues 405 "Method not allowed", JSON requested response # RenameRepository.feature:44
    Given There is a default multirepo server                                                                             # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "GET /repos/repo1/rename.json?name=renamedRepo"                                                           # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                                                                              # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "POST"                                                                     # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Trying to assign a duplicated name to a repo issues 400 "Bad request", JSON requested response # RenameRepository.feature:51
    Given There is a default multirepo server                                                              # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "POST /repos/repo1/rename.json?name=repo2"                                                 # WebAPICucumberHooks.callURL(String)
    Then the response status should be '400'                                                               # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "application/json"                                              # WebAPICucumberHooks.checkContentType(String)
    And the json object "response.success" equals "false"                                                  # WebAPICucumberHooks.checkJSONResponse(String,String)
    And the json object "response.error" equals "A repository with that name already exists."              # WebAPICucumberHooks.checkJSONResponse(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Renaming a repository returns a link to the new location issues 301 "Moved permanently", JSON requested response # RenameRepository.feature:59
    Given There is a default multirepo server                                                                                # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "POST /repos/repo1/rename.json?name=repo1Renamed"                                                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '301'                                                                                 # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "application/json"                                                                # WebAPICucumberHooks.checkContentType(String)
    And the json object "response.success" equals "true"                                                                     # WebAPICucumberHooks.checkJSONResponse(String,String)
    And the json object "response.repo.name" equals "repo1Renamed"                                                           # WebAPICucumberHooks.checkJSONResponse(String,String)
    And the json object "response.repo.href" ends with "/repos/repo1Renamed.json"                                            # WebAPICucumberHooks.checkJSONResponseEndsWith(String,String)
@Commands @ReportMergeScenario
Feature: ReportMergeScenario
  The ReportMergeScenario command allows a user to see the results of a merge between two branches and is supported through the "/repos/{repository}/reportMergeScenario" endpoint
  The command must be executed using the HTTP GET method
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method issues 405 "Method not allowed" # ReportMergeScenario.feature:6
    Given There is an empty repository named repo1                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/reportMergeScenario"               # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                 # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ReportMergeScenario outside of a repository issues 404 "Not found"              # ReportMergeScenario.feature:12
    Given There is an empty multirepo server                                                # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/reportMergeScenario?ourCommit=master&theirCommit=branch1" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                                                # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"                                     # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"                             # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling ReportMergeScenario with no "our" commit issues a 500 status code                # ReportMergeScenario.feature:19
    Given There is an empty repository named repo1                                                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/reportMergeScenario?theirCommit=branch1"                           # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                         # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "Required parameter 'ourCommit' was not provided." # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling ReportMergeScenario with no "their" commit issues a 500 status code                # ReportMergeScenario.feature:25
    Given There is an empty repository named repo1                                                     # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/reportMergeScenario?ourCommit=master"                                # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                           # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "Required parameter 'theirCommit' was not provided." # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling ReportMergeScenario with an invalid "our" commit issues a 500 status code              # ReportMergeScenario.feature:31
    Given There is a repository with multiple branches named repo1                                         # WebAPICucumberHooks.setUpMultipleBranches(String)
    When I call "GET /repos/repo1/reportMergeScenario?ourCommit=nonexistent&theirCommit=branch1"           # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                               # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "'our' commit could not be resolved to a commit object." # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling ReportMergeScenario with an invalid "their" commit issues a 500 status code              # ReportMergeScenario.feature:37
    Given There is a repository with multiple branches named repo1                                           # WebAPICucumberHooks.setUpMultipleBranches(String)
    When I call "GET /repos/repo1/reportMergeScenario?ourCommit=master&theirCommit=nonexistent"              # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                                 # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "'their' commit could not be resolved to a commit object." # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ReportMergeScenario with two valid commits returns the details of the merge             # ReportMergeScenario.feature:43
    Given There is a repository with multiple branches named repo1                                  # WebAPICucumberHooks.setUpMultipleBranches(String)
    When I call "GET /repos/repo1/reportMergeScenario?ourCommit=master&theirCommit=non_conflicting" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                        # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                          # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/change/text()" equals "ADDED"                            # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/id/text()" equals "Points/Point.2"                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/geometry/text()" equals "POINT (-10 -10)"                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/crs/text()" equals "EPSG:4326"                           # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ReportMergeScenario with conflicting commits returns the details of the merge                       # ReportMergeScenario.feature:53
    Given There is a repository with multiple branches named repo1                                              # WebAPICucumberHooks.setUpMultipleBranches(String)
    When I call "GET /repos/repo1/reportMergeScenario?ourCommit=master&theirCommit=conflicting"                 # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                    # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                      # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/change/text()" equals "CONFLICT"                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/id/text()" equals "Points/Point.1"                                   # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/ourvalue/text()" equals "{@ObjectId|repo1|master:Points/Point.1}"    # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/theirvalue/text()" equals "0000000000000000000000000000000000000000" # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/geometry/text()" equals "POINT (0 0)"                                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/crs/text()" equals "EPSG:4326"                                       # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ReportMergeScenario supports paging                                                                        # ReportMergeScenario.feature:65
    Given There is a default multirepo server                                                                          # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "GET /repos/repo1/reportMergeScenario?ourCommit=master~2&theirCommit=branch1&elementsPerPage=2&page=0" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                           # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Merge/Feature" 2 times                                              # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the response body should contain "Points/Point.2"                                                              # WebAPICucumberHooks.checkResponseTextContains(String)
    And the response body should contain "Polygons/Polygon.2"                                                          # WebAPICucumberHooks.checkResponseTextContains(String)
    When I call "GET /repos/repo1/reportMergeScenario?ourCommit=master~2&theirCommit=branch1&elementsPerPage=2&page=1" # WebAPICucumberHooks.callURL(String)
    And the xpath "/response/success/text()" equals "true"                                                             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Merge/Feature" 1 times                                              # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the response body should contain "Lines/Line.2"                                                                # WebAPICucumberHooks.checkResponseTextContains(String)
@Commands @ResolveConflict
Feature: ResolveConflict
  The ResolveConflict command allows a user to resolve a conflict with a specific objectId and is supported through the "/repos/{repository}/resolveconflict" endpoint
  The command must be executed using the HTTP GET method
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method issues 405 "Method not allowed" # ResolveConflict.feature:6
    Given There is an empty repository named repo1                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/resolveconflict"                   # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                 # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ResolveConflict outside of a transaction issues 500 "Transaction required" # ResolveConflict.feature:12
    Given There is an empty repository named repo1                                     # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/resolveconflict?path=somePath/1&objectid=someId"     # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                           # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "No transaction was specified"     # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ResolveConflict outside of a repository issues 404 "Not found"         # ResolveConflict.feature:18
    Given There is an empty multirepo server                                       # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/resolveconflict?path=somePath/1&objectid=someId" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                                       # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"                            # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"                    # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ResolveConflict without a path issues a 500 status code                               # ResolveConflict.feature:25
    Given There is an empty repository named repo1                                                # WebAPICucumberHooks.setUpEmptyRepo(String)
    And I have a transaction as "@txId" on the "repo1" repo                                       # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/resolveconflict?transactionId={@txId}&objectid=someId"          # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                      # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "Required parameter 'path' was not provided." # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ResolveConflict without an object ID issues a 500 status code                             # ResolveConflict.feature:32
    Given There is an empty repository named repo1                                                    # WebAPICucumberHooks.setUpEmptyRepo(String)
    And I have a transaction as "@txId" on the "repo1" repo                                           # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/resolveconflict?transactionId={@txId}&path=Points/Point.1"          # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                          # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "Required parameter 'objectid' was not provided." # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ResolveConflict with an invalid path issues a 400 status code                                                                   # ResolveConflict.feature:39
    Given There is an empty repository named repo1                                                                                          # WebAPICucumberHooks.setUpEmptyRepo(String)
    And I have a transaction as "@txId" on the "repo1" repo                                                                                 # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And There are conflicts on the "repo1" repo in the @txId transaction                                                                    # WebAPICucumberHooks.There_are_conflict(String,String)
    When I call "GET /repos/repo1/resolveconflict?transactionId={@txId}&path=Points&objectid={@ObjectId|repo1|@txId|master:Points/Point.1}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '400'                                                                                                # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "empty child path: '/'"                                                                   # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: ResolveConflict with valid parameters resolves the conflict                                                                               # ResolveConflict.feature:47
    Given There is an empty repository named repo1                                                                                                    # WebAPICucumberHooks.setUpEmptyRepo(String)
    And I have a transaction as "@txId" on the "repo1" repo                                                                                           # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And There are conflicts on the "repo1" repo in the @txId transaction                                                                              # WebAPICucumberHooks.There_are_conflict(String,String)
    When I call "GET /repos/repo1/resolveconflict?transactionId={@txId}&path=Points/Point.1&objectid={@ObjectId|repo1|@txId|master~1:Points/Point.1}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                          # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                                                            # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Add/text()" equals "Success"                                                                                             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And There should be no conflicts on the "repo1" repo in the @txId transaction                                                                     # WebAPICucumberHooks.There_should_be_no_conflicts(String,String)
    And the variable "{@ObjectId|repo1|@txId|STAGE_HEAD:Points/Point.1}" equals "{@ObjectId|repo1|@txId|master~1:Points/Point.1}"                     # WebAPICucumberHooks.checkVariableEquals(String,String)
@Commands @RevertFeature
Feature: RevertFeature
  The RevertFeature command allows a user to undo the changes made to a feature and is supported through the "/repos/{repository}/revertfeature" endpoint
  The command must be executed using the HTTP GET method
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method issues 405 "Method not allowed" # RevertFeature.feature:6
    Given There is an empty repository named repo1                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/revertfeature"                     # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                 # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: RevertFeature outside of a transaction issues 500 "Transaction required"                   # RevertFeature.feature:12
    Given There is an empty repository named repo1                                                     # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/revertfeature?path=somePath/1&newCommitId=someId&oldCommitId=someId" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                           # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "No transaction was specified"                     # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: RevertFeature outside of a repository issues 404 "Not found"                               # RevertFeature.feature:18
    Given There is an empty multirepo server                                                           # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/revertfeature?path=somePath/1&newCommitId=someId&oldCommitId=someId" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                                                           # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"                                                # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"                                        # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: RevertFeature without a path issues a 500 status code                                                                                # RevertFeature.feature:25
    Given There is a default multirepo server                                                                                                    # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I have a transaction as "@txId" on the "repo1" repo                                                                                      # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&oldCommitId={@ObjectId|repo1|master}&newCommitId={@ObjectId|repo1|master}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "Required parameter 'path' was not provided."                                                # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: RevertFeature without a new commit ID issues a 500 status code                                                      # RevertFeature.feature:32
    Given There is a default multirepo server                                                                                   # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I have a transaction as "@txId" on the "repo1" repo                                                                     # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=Points/Point.1&oldCommitId={@ObjectId|repo1|master}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                                                    # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "Required parameter 'newCommitId' was not provided."                        # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: RevertFeature without an old commit ID issues a 500 status code                                                     # RevertFeature.feature:39
    Given There is a default multirepo server                                                                                   # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I have a transaction as "@txId" on the "repo1" repo                                                                     # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=Points/Point.1&newCommitId={@ObjectId|repo1|master}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                                                    # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "Required parameter 'oldCommitId' was not provided."                        # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: RevertFeature with an invalid path issues a 500 status code                                                                                             # RevertFeature.feature:46
    Given There is a default multirepo server                                                                                                                       # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I have a transaction as "@txId" on the "repo1" repo                                                                                                         # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=nonexistent&oldCommitId={@ObjectId|repo1|master~1}&newCommitId={@ObjectId|repo1|master}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                                                                                        # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "The feature was not found in either commit tree."                                                                # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: RevertFeature on an added feature removes that feature                                                                                                     # RevertFeature.feature:53
    Given There is a default multirepo server                                                                                                                          # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I have a transaction as "@txId" on the "repo1" repo                                                                                                            # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=Points/Point.3&oldCommitId={@ObjectId|repo1|master~1}&newCommitId={@ObjectId|repo1|master}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                           # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                                                                             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the repo1 repository's "master" in the @txId transaction should have the following features:                                                                   # WebAPICucumberHooks.verifyRepositoryContentsTx(String,String,String,DataTable)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: RevertFeature on a modified feature undoes the change                                                                                                      # RevertFeature.feature:65
    Given There is an empty repository named repo1                                                                                                                     # WebAPICucumberHooks.setUpEmptyRepo(String)
    And There is a feature with multiple authors on the "repo1" repo                                                                                                   # WebAPICucumberHooks.There_is_a_feature_with_multiple_authors(String)
    And I have a transaction as "@txId" on the "repo1" repo                                                                                                            # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=Points/Point.1&oldCommitId={@ObjectId|repo1|master~1}&newCommitId={@ObjectId|repo1|master}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                           # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                                                                             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the variable "{@ObjectId|repo1|@txId|master:Points/Point.1}" equals "{@ObjectId|repo1|@txId|master~2:Points/Point.1}"                                          # WebAPICucumberHooks.checkVariableEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: RevertFeature on a removed feature adds it back                                                                                                                      # RevertFeature.feature:74
    Given There is a repository with multiple branches named repo1                                                                                                               # WebAPICucumberHooks.setUpMultipleBranches(String)
    And I have checked out "conflicting" on the "repo1" repo                                                                                                                     # WebAPICucumberHooks.I_have_checked_out(String,String)
    And I have a transaction as "@txId" on the "repo1" repo                                                                                                                      # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And the repo1 repository's "conflicting" in the @txId transaction should have the following features:                                                                        # WebAPICucumberHooks.verifyRepositoryContentsTx(String,String,String,DataTable)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=Points/Point.1&oldCommitId={@ObjectId|repo1|conflicting~1}&newCommitId={@ObjectId|repo1|conflicting}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                                                                                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the repo1 repository's "conflicting" in the @txId transaction should have the following features:                                                                        # WebAPICucumberHooks.verifyRepositoryContentsTx(String,String,String,DataTable)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: If a feature has changed since the 'new' commit id, conflicts may be thrown                                                                                                        # RevertFeature.feature:88
    Given There is a repository with multiple branches named repo1                                                                                                                             # WebAPICucumberHooks.setUpMultipleBranches(String)
    And I have checked out "conflicting" on the "repo1" repo                                                                                                                                   # WebAPICucumberHooks.I_have_checked_out(String,String)
    And I have a transaction as "@txId" on the "repo1" repo                                                                                                                                    # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And I have committed "Point.1_modified" on the "repo1" repo in the "@txId" transaction                                                                                                     # WebAPICucumberHooks.I_have_committed(String,String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=Points/Point.1&oldCommitId={@ObjectId|repo1|@txId|conflicting~2}&newCommitId={@ObjectId|repo1|@txId|conflicting~1}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                                                                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/conflicts/text()" equals "1"                                                                                                                                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/change/text()" equals "CONFLICT"                                                                                                                    # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/id/text()" equals "Points/Point.1"                                                                                                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/ourvalue/text()" equals "{@ObjectId|repo1|@txId|conflicting:Points/Point.1}"                                                                        # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/theirvalue/text()" equals "{@ObjectId|repo1|@txId|conflicting~2:Points/Point.1}"                                                                    # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Supplying author information applies to the reverted commit as well as the merge commit                                                                                                                        # RevertFeature.feature:102
    Given There is an empty repository named repo1                                                                                                                                                                         # WebAPICucumberHooks.setUpEmptyRepo(String)
    And There is a feature with multiple authors on the "repo1" repo                                                                                                                                                       # WebAPICucumberHooks.There_is_a_feature_with_multiple_authors(String)
    And I have a transaction as "@txId" on the "repo1" repo                                                                                                                                                                # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And I have committed "Point.2" on the "repo1" repo in the "@txId" transaction                                                                                                                                          # WebAPICucumberHooks.I_have_committed(String,String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=Points/Point.1&oldCommitId={@ObjectId|repo1|master~1}&newCommitId={@ObjectId|repo1|master}&authorName=myAuthor&authorEmail=myAuthor@geogig.org" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                                                                               # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                                                                                                                                 # WebAPICucumberHooks.checkXPathEquals(String,String)
    When I call "GET /repos/repo1/cat?objectid={@ObjectId|repo1|@txId|master}"                                                                                                                                             # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                                                                               # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/commit/author/name/text()" equals "myAuthor"                                                                                                                                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/commit/author/email/text()" equals "myAuthor@geogig.org"                                                                                                                                      # WebAPICucumberHooks.checkXPathEquals(String,String)
    When I call "GET /repos/repo1/cat?objectid={@ObjectId|repo1|@txId|master^2}"                                                                                                                                           # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                                                                               # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/commit/author/name/text()" equals "myAuthor"                                                                                                                                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/commit/author/email/text()" equals "myAuthor@geogig.org"                                                                                                                                      # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Supplying a commit message applies to the revert commit                                                                                                                               # RevertFeature.feature:119
    Given There is an empty repository named repo1                                                                                                                                                # WebAPICucumberHooks.setUpEmptyRepo(String)
    And There is a feature with multiple authors on the "repo1" repo                                                                                                                              # WebAPICucumberHooks.There_is_a_feature_with_multiple_authors(String)
    And I have a transaction as "@txId" on the "repo1" repo                                                                                                                                       # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And I have committed "Point.2" on the "repo1" repo in the "@txId" transaction                                                                                                                 # WebAPICucumberHooks.I_have_committed(String,String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=Points/Point.1&oldCommitId={@ObjectId|repo1|master~1}&newCommitId={@ObjectId|repo1|master}&commitMessage=My%20Message" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                                                      # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                                                                                                        # WebAPICucumberHooks.checkXPathEquals(String,String)
    When I call "GET /repos/repo1/cat?objectid={@ObjectId|repo1|@txId|master^2}"                                                                                                                  # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                                                      # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/commit/message/text()" equals "My Message"                                                                                                                           # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Supplying a merge message applies to the merge commit                                                                                                                                # RevertFeature.feature:131
    Given There is an empty repository named repo1                                                                                                                                               # WebAPICucumberHooks.setUpEmptyRepo(String)
    And There is a feature with multiple authors on the "repo1" repo                                                                                                                             # WebAPICucumberHooks.There_is_a_feature_with_multiple_authors(String)
    And I have a transaction as "@txId" on the "repo1" repo                                                                                                                                      # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And I have committed "Point.2" on the "repo1" repo in the "@txId" transaction                                                                                                                # WebAPICucumberHooks.I_have_committed(String,String,String)
    When I call "GET /repos/repo1/revertfeature?transactionId={@txId}&path=Points/Point.1&oldCommitId={@ObjectId|repo1|master~1}&newCommitId={@ObjectId|repo1|master}&mergeMessage=My%20Message" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                                                                                                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    When I call "GET /repos/repo1/cat?objectid={@ObjectId|repo1|@txId|master}"                                                                                                                   # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                                                                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/commit/message/text()" equals "My Message"                                                                                                                          # WebAPICucumberHooks.checkXPathEquals(String,String)
@Commands @Statistics
Feature: Statistics
  The Statistics command allows a user to summarize the changes made to a branch and is supported through the "/repos/{repository}/statistics" endpoint
  The command must be executed using the HTTP GET method
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method issues 405 "Method not allowed" # Statistics.feature:6
    Given There is an empty repository named repo1                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/statistics"                        # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                 # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Statistics outside of a repository issues 404 "Not found" # Statistics.feature:12
    Given There is an empty multirepo server                          # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/statistics"                         # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                          # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"               # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"       # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Statistics summarizes the changes made to the repository                                             # Statistics.feature:19
    Given There is a default multirepo server                                                                    # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "GET /repos/repo1/statistics"                                                                    # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Statistics/FeatureTypes/FeatureType" 3 times                  # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And there is an xpath "/response/Statistics/FeatureTypes/FeatureType/name/text()" that contains "Points"     # WebAPICucumberHooks.checkOneXPathValueContains(String,String)
    And there is an xpath "/response/Statistics/FeatureTypes/FeatureType/name/text()" that contains "Lines"      # WebAPICucumberHooks.checkOneXPathValueContains(String,String)
    And there is an xpath "/response/Statistics/FeatureTypes/FeatureType/name/text()" that contains "Polygons"   # WebAPICucumberHooks.checkOneXPathValueContains(String,String)
    And the xpath "/response/Statistics/FeatureTypes/totalFeatureTypes/text()" equals "3"                        # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/FeatureTypes/totalFeatures/text()" equals "9"                            # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/latestCommit/id/text()" equals "{@ObjectId|repo1|master}"                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/latestCommit/message/text()" contains "merge branch branch2 onto master" # WebAPICucumberHooks.checkXPathValueContains(String,String)
    And the xpath "/response/Statistics/firstCommit/id/text()" equals "{@ObjectId|repo1|master~2}"               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/firstCommit/message/text()" contains "point1, line1, poly1"              # WebAPICucumberHooks.checkXPathValueContains(String,String)
    And the xpath "/response/Statistics/Authors/Author/name/text()" equals "geogigUser"                          # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/Authors/Author/email/text()" equals "repo1_Owner@geogig.org"             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/Authors/totalAuthors/text()" equals "1"                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Statistics summarizes the changes since a particular timestamp up to a specific commit               # Statistics.feature:38
    Given There is a default multirepo server                                                                    # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "GET /repos/repo1/statistics?since=0&branch=master~1"                                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Statistics/FeatureTypes/FeatureType" 3 times                  # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And there is an xpath "/response/Statistics/FeatureTypes/FeatureType/name/text()" that equals "Points"       # WebAPICucumberHooks.checkOneXPathEquals(String,String)
    And there is an xpath "/response/Statistics/FeatureTypes/FeatureType/numFeatures/text()" that equals "2"     # WebAPICucumberHooks.checkOneXPathEquals(String,String)
    And there is an xpath "/response/Statistics/FeatureTypes/FeatureType/name/text()" that equals "Lines"        # WebAPICucumberHooks.checkOneXPathEquals(String,String)
    And there is an xpath "/response/Statistics/FeatureTypes/FeatureType/name/text()" that equals "Polygons"     # WebAPICucumberHooks.checkOneXPathEquals(String,String)
    And the xpath "/response/Statistics/FeatureTypes/totalFeatureTypes/text()" equals "3"                        # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/FeatureTypes/totalFeatures/text()" equals "6"                            # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/latestCommit/id/text()" equals "{@ObjectId|repo1|master~1}"              # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/latestCommit/message/text()" contains "merge branch branch1 onto master" # WebAPICucumberHooks.checkXPathValueContains(String,String)
    And the xpath "/response/Statistics/firstCommit/id/text()" equals "{@ObjectId|repo1|master~2}"               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/firstCommit/message/text()" contains "point1, line1, poly1"              # WebAPICucumberHooks.checkXPathValueContains(String,String)
    And the xpath "/response/Statistics/Authors/Author/name/text()" equals "geogigUser"                          # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/Authors/Author/email/text()" equals "repo1_Owner@geogig.org"             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/Authors/totalAuthors/text()" equals "1"                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Statistics can summarize the changes made to a specific path                                         # Statistics.feature:58
    Given There is a default multirepo server                                                                    # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "GET /repos/repo1/statistics?path=Points"                                                        # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Statistics/FeatureTypes/FeatureType" 1 times                  # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xpath "/response/Statistics/FeatureTypes/FeatureType/name/text()" equals "Points"                    # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/FeatureTypes/FeatureType/numFeatures/text()" equals "3"                  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/latestCommit/id/text()" equals "{@ObjectId|repo1|master}"                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/latestCommit/message/text()" contains "merge branch branch2 onto master" # WebAPICucumberHooks.checkXPathValueContains(String,String)
    And the xpath "/response/Statistics/firstCommit/id/text()" equals "{@ObjectId|repo1|master~2}"               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/firstCommit/message/text()" contains "point1, line1, poly1"              # WebAPICucumberHooks.checkXPathValueContains(String,String)
    And the xpath "/response/Statistics/Authors/Author/name/text()" equals "geogigUser"                          # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/Authors/Author/email/text()" equals "repo1_Owner@geogig.org"             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Statistics/Authors/totalAuthors/text()" equals "1"                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
@Commands @Status
Feature: Status
  The Status command allows a user to see the current state of the repository and is supported through the "/repos/{repository}/status" endpoint
  The command must be executed using the HTTP GET method
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method issues 405 "Method not allowed" # Status.feature:6
    Given There is an empty repository named repo1                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/status"                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                 # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Status outside of a repository issues 404 "Not found" # Status.feature:12
    Given There is an empty multirepo server                      # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/status"                         # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                      # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"           # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"   # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Status shows the current branch and all staged and unstaged features # Status.feature:19
    Given There is an empty repository named repo1                               # WebAPICucumberHooks.setUpEmptyRepo(String)
    And I have a transaction as "@txId" on the "repo1" repo                      # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And I have staged "Line.1" on the "repo1" repo in the "@txId" transaction    # WebAPICucumberHooks.I_have_staged(String,String,String)
    And I have unstaged "Point.1" on the "repo1" repo in the "@txId" transaction # WebAPICucumberHooks.I_have_unstaged(String,String,String)
    And I have unstaged "Point.2" on the "repo1" repo in the "@txId" transaction # WebAPICucumberHooks.I_have_unstaged(String,String,String)
    When I call "GET /repos/repo1/status?transactionId={@txId}"                  # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/header/branch/text()" equals "master"               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/staged/changeType/text()" equals "ADDED"            # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/staged/newPath/text()" equals "Lines/Line.1"        # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/unstaged" 2 times             # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the response body should contain "Points/Point.1"                        # WebAPICucumberHooks.checkResponseTextContains(String)
    And the response body should contain "Points/Point.2"                        # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Status shows conflicted features                                                                    # Status.feature:35
    Given There is an empty repository named repo1                                                              # WebAPICucumberHooks.setUpEmptyRepo(String)
    And I have a transaction as "@txId" on the "repo1" repo                                                     # WebAPICucumberHooks.beginTransactionAsVariable(String,String)
    And There are conflicts on the "repo1" repo in the @txId transaction                                        # WebAPICucumberHooks.There_are_conflict(String,String)
    When I call "GET /repos/repo1/status?transactionId={@txId}"                                                 # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                    # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                      # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/header/branch/text()" equals "master"                                              # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/unmerged/changeType/text()" equals "CONFLICT"                                      # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/unmerged/path/text()" equals "Points/Point.1"                                      # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/unmerged/ours/text()" equals "{@ObjectId|repo1|@txId|master:Points/Point.1}"       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/unmerged/theirs/text()" equals "0000000000000000000000000000000000000000"          # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/unmerged/ancestor/text()" equals "{@ObjectId|repo1|@txId|master~1:Points/Point.1}" # WebAPICucumberHooks.checkXPathEquals(String,String)
@Commands @Tag
Feature: Tag
  The Tag command allows a user to create, list, and delete tags and is supported through the "/repos/{repository}/tag" endpoint
  The command must be executed using the HTTP GET, POST, or DELETE methods
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method issues 405 "Method not allowed" # Tag.feature:6
    Given There is an empty repository named repo1                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/tag"                               # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET,POST,DELETE"     # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Tag outside of a repository issues 404 "Not found"  # Tag.feature:12
    Given There is an empty multirepo server                    # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/tag"                          # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                    # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"         # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found" # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Issuing a POST request to tag without a name issues a 500 status code                                                              # Tag.feature:19
    Given There is an empty repository named repo1                                                                                             # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "POST /repos/repo1/tag"                                                                                                        # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "You must specify list or delete, or provide a name, message, and commit for the new tag." # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Issuing a POST request to tag without a commit issues a 500 status code                  # Tag.feature:25
    Given There is an empty repository named repo1                                                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "POST /repos/repo1/tag?name=newTag"                                                  # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                         # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "You must specify a commit to point the tag to." # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Issuing a POST request to tag with an invalid commit issues a 500 status code  # Tag.feature:31
    Given There is an empty repository named repo1                                         # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "POST /repos/repo1/tag?name=newTag&commit=nonexistent"                     # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                               # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "'nonexistent' could not be resolved." # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Issuing a POST request to tag with valid parameters creates a tag         # Tag.feature:37
    Given There is a default multirepo server                                         # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "POST /repos/repo1/tag?name=newTag&commit=master&message=My%20Tag"    # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                          # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                            # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Tag/id" 1 times                    # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xpath "/response/Tag/commitid/text()" equals "{@ObjectId|repo1|master}"   # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Tag/name/text()" equals "newTag"                         # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Tag/message/text()" equals "My Tag"                      # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Tag/tagger/name/text()" equals "geogigUser"              # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Tag/tagger/email/text()" equals "repo1_Owner@geogig.org" # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Tag/tagger/timestamp" 1 times      # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/Tag/tagger/timeZoneOffset" 1 times # WebAPICucumberHooks.checkXPathCadinality(String,int)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Issuing a GET request to tag lists all tags                                           # Tag.feature:51
    Given There is a default multirepo server                                                     # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I call "POST /repos/repo1/tag?name=tag1&commit=master&message=My%20Tag%201"               # WebAPICucumberHooks.callURL(String)
    And I call "POST /repos/repo1/tag?name=tag2&commit=branch1&message=My%20Tag%202"              # WebAPICucumberHooks.callURL(String)
    When I call "GET /repos/repo1/tag"                                                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                      # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                        # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Tag" 2 times                                   # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And there is an xpath "/response/Tag/commitid/text()" that equals "{@ObjectId|repo1|master}"  # WebAPICucumberHooks.checkOneXPathEquals(String,String)
    And there is an xpath "/response/Tag/name/text()" that equals "tag1"                          # WebAPICucumberHooks.checkOneXPathEquals(String,String)
    And there is an xpath "/response/Tag/message/text()" that equals "My Tag 1"                   # WebAPICucumberHooks.checkOneXPathEquals(String,String)
    And there is an xpath "/response/Tag/commitid/text()" that equals "{@ObjectId|repo1|branch1}" # WebAPICucumberHooks.checkOneXPathEquals(String,String)
    And there is an xpath "/response/Tag/name/text()" that equals "tag2"                          # WebAPICucumberHooks.checkOneXPathEquals(String,String)
    And there is an xpath "/response/Tag/message/text()" that equals "My Tag 2"                   # WebAPICucumberHooks.checkOneXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Issuing a DELETE request to tag without a name issues a 500 status code          # Tag.feature:66
    Given There is an empty repository named repo1                                           # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "DELETE /repos/repo1/tag"                                                    # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                 # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "You must specify the tag name to delete." # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Issuing a DELETE request to tag deletes the tag                                  # Tag.feature:72
    Given There is a default multirepo server                                                # WebAPICucumberHooks.setUpDefaultMultiRepo()
    And I call "POST /repos/repo1/tag?name=tag1&commit=master&message=My%20Tag%201"          # WebAPICucumberHooks.callURL(String)
    And I call "POST /repos/repo1/tag?name=tag2&commit=branch1&message=My%20Tag%202"         # WebAPICucumberHooks.callURL(String)
    When I call "DELETE /repos/repo1/tag?name=tag1"                                          # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                 # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                   # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/DeletedTag/id" 1 times                    # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xpath "/response/DeletedTag/commitid/text()" equals "{@ObjectId|repo1|master}"   # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/DeletedTag/name/text()" equals "tag1"                           # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/DeletedTag/message/text()" equals "My Tag 1"                    # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/DeletedTag/tagger/name/text()" equals "geogigUser"              # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/DeletedTag/tagger/email/text()" equals "repo1_Owner@geogig.org" # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/DeletedTag/tagger/timestamp" 1 times      # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/DeletedTag/tagger/timeZoneOffset" 1 times # WebAPICucumberHooks.checkXPathCadinality(String,int)
    When I call "GET /repos/repo1/tag"                                                       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                 # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                   # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Tag/id" 1 times                           # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xpath "/response/Tag/commitid/text()" equals "{@ObjectId|repo1|branch1}"         # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Tag/name/text()" equals "tag2"                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Tag/message/text()" equals "My Tag 2"                           # WebAPICucumberHooks.checkXPathEquals(String,String)
@Commands @Transaction
Feature: Transaction
  Transactions allow a user to perform work without affecting the main repository is supported through the "/repos/{repository}/beginTransaction" endpoint
  The command must be executed using the HTTP GET method
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method on begin transaction issues 405 "Method not allowed" # Transaction.feature:6
    Given There is an empty repository named repo1                                        # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/beginTransaction"                                       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                                              # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                                      # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Beginning a transaction outside of a repository issues 404 "Not found" # Transaction.feature:12
    Given There is an empty multirepo server                                       # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/beginTransaction"                                # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                                       # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"                            # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"                    # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method on end transaction issues 405 "Method not allowed" # Transaction.feature:19
    Given There is an empty repository named repo1                                      # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/endTransaction"                                       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                                            # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                                    # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Ending a transaction outside of a repository issues 404 "Not found" # Transaction.feature:25
    Given There is an empty multirepo server                                    # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/endTransaction"                               # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                                    # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"                         # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"                 # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Ending a transaction outside of a transaction issues 500 "Transaction required" # Transaction.feature:32
    Given There is an empty repository named repo1                                          # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/endTransaction"                                           # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" contains "No transaction was specified"          # WebAPICucumberHooks.checkXPathValueContains(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Work on a transaction does not affect the main repository                     # Transaction.feature:38
    Given There is a repository with multiple branches named repo1                        # WebAPICucumberHooks.setUpMultipleBranches(String)
    When I call "GET /repos/repo1/beginTransaction"                                       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                              # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Transaction/ID"                        # WebAPICucumberHooks.checkResponseContainsXPath(String)
    And I save the response "/response/Transaction/ID/text()" as "@txId"                  # WebAPICucumberHooks.saveResponseXPathValueAsVariable(String,String)
    When I have committed "Point.2" on the "repo1" repo in the "@txId" transaction        # WebAPICucumberHooks.I_have_committed(String,String,String)
    Then the variable "{@ObjectId|repo1|master:Points/Point.2}" equals ""                 # WebAPICucumberHooks.checkVariableEquals(String,String)
    And the variable "{@ObjectId|repo1|@txId|master~1}" equals "{@ObjectId|repo1|master}" # WebAPICucumberHooks.checkVariableEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Ending a transaction moves the work to the main repository                           # Transaction.feature:49
    Given There is a repository with multiple branches named repo1                               # WebAPICucumberHooks.setUpMultipleBranches(String)
    When I call "GET /repos/repo1/beginTransaction"                                              # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Transaction/ID"                               # WebAPICucumberHooks.checkResponseContainsXPath(String)
    And I save the response "/response/Transaction/ID/text()" as "@txId"                         # WebAPICucumberHooks.saveResponseXPathValueAsVariable(String,String)
    When I have committed "Point.2" on the "repo1" repo in the "@txId" transaction               # WebAPICucumberHooks.I_have_committed(String,String,String)
    Then the variable "{@ObjectId|repo1|master:Points/Point.2}" equals ""                        # WebAPICucumberHooks.checkVariableEquals(String,String)
    And the variable "{@ObjectId|repo1|@txId|master~1}" equals "{@ObjectId|repo1|master}"        # WebAPICucumberHooks.checkVariableEquals(String,String)
    When I call "GET /repos/repo1/endTransaction?transactionId={@txId}"                          # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Transaction/ID/text()" equals "{@txId}"                             # WebAPICucumberHooks.checkXPathEquals(String,String)
    When I call "GET /repos/repo1/cat?objectid={@ObjectId|repo1|master:Points/Point.2}"          # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/feature/id/text()" equals "{@ObjectId|repo1|master:Points/Point.2}" # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/feature/attribute" 3 times                    # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the response body should contain "StringProp1_2"                                         # WebAPICucumberHooks.checkResponseTextContains(String)
    And the response body should contain "2000"                                                  # WebAPICucumberHooks.checkResponseTextContains(String)
    And the response body should contain "POINT (-10 -10)"                                       # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Canceling a transaction leaves the main repository without changes            # Transaction.feature:72
    Given There is a repository with multiple branches named repo1                        # WebAPICucumberHooks.setUpMultipleBranches(String)
    When I call "GET /repos/repo1/beginTransaction"                                       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                              # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Transaction/ID"                        # WebAPICucumberHooks.checkResponseContainsXPath(String)
    And I save the response "/response/Transaction/ID/text()" as "@txId"                  # WebAPICucumberHooks.saveResponseXPathValueAsVariable(String,String)
    When I have committed "Point.2" on the "repo1" repo in the "@txId" transaction        # WebAPICucumberHooks.I_have_committed(String,String,String)
    Then the variable "{@ObjectId|repo1|master:Points/Point.2}" equals ""                 # WebAPICucumberHooks.checkVariableEquals(String,String)
    And the variable "{@ObjectId|repo1|@txId|master~1}" equals "{@ObjectId|repo1|master}" # WebAPICucumberHooks.checkVariableEquals(String,String)
    When I call "GET /repos/repo1/endTransaction?transactionId={@txId}&cancel=true"       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                              # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Transaction/ID/text()" equals "{@txId}"                      # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the variable "{@ObjectId|repo1|master:Points/Point.2}" equals ""                  # WebAPICucumberHooks.checkVariableEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Ending a transaction with conflicting changes returns details of the conflict                      # Transaction.feature:88
    Given There is a repository with multiple branches named repo1                                             # WebAPICucumberHooks.setUpMultipleBranches(String)
    When I call "GET /repos/repo1/beginTransaction"                                                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Transaction/ID"                                             # WebAPICucumberHooks.checkResponseContainsXPath(String)
    And I save the response "/response/Transaction/ID/text()" as "@txId"                                       # WebAPICucumberHooks.saveResponseXPathValueAsVariable(String,String)
    When I call "GET /repos/repo1/beginTransaction"                                                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Transaction/ID"                                             # WebAPICucumberHooks.checkResponseContainsXPath(String)
    And I save the response "/response/Transaction/ID/text()" as "@txId2"                                      # WebAPICucumberHooks.saveResponseXPathValueAsVariable(String,String)
    When I have removed "Point.1_modified" on the "repo1" repo in the "@txId" transaction                      # WebAPICucumberHooks.I_have_removed(String,String,String)
    And I have committed "Point.1" on the "repo1" repo in the "@txId2" transaction                             # WebAPICucumberHooks.I_have_committed(String,String,String)
    When I call "GET /repos/repo1/endTransaction?transactionId={@txId2}"                                       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Transaction/ID/text()" equals "{@txId2}"                                          # WebAPICucumberHooks.checkXPathEquals(String,String)
    When I call "GET /repos/repo1/endTransaction?transactionId={@txId}"                                        # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/theirs/text()" equals "{@ObjectId|repo1|master}"                            # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/ours/text()" equals "{@ObjectId|repo1|@txId|master}"                        # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/ancestor/text()" equals "{@ObjectId|repo1|master~1}"                        # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/conflicts/text()" equals "1"                                                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/change/text()" equals "CONFLICT"                                    # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/id/text()" equals "Points/Point.1"                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/ourvalue/text()" equals "0000000000000000000000000000000000000000"  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/theirvalue/text()" equals "{@ObjectId|repo1|master:Points/Point.1}" # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Fixing transaction conflicts and ending again is successful                                        # Transaction.feature:118
    Given There is a repository with multiple branches named repo1                                             # WebAPICucumberHooks.setUpMultipleBranches(String)
    When I call "GET /repos/repo1/beginTransaction"                                                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Transaction/ID"                                             # WebAPICucumberHooks.checkResponseContainsXPath(String)
    And I save the response "/response/Transaction/ID/text()" as "@txId"                                       # WebAPICucumberHooks.saveResponseXPathValueAsVariable(String,String)
    When I call "GET /repos/repo1/beginTransaction"                                                            # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/Transaction/ID"                                             # WebAPICucumberHooks.checkResponseContainsXPath(String)
    And I save the response "/response/Transaction/ID/text()" as "@txId2"                                      # WebAPICucumberHooks.saveResponseXPathValueAsVariable(String,String)
    And I have removed "Point.1_modified" on the "repo1" repo in the "@txId" transaction                       # WebAPICucumberHooks.I_have_removed(String,String,String)
    And I have committed "Point.1" on the "repo1" repo in the "@txId2" transaction                             # WebAPICucumberHooks.I_have_committed(String,String,String)
    When I call "GET /repos/repo1/endTransaction?transactionId={@txId2}"                                       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Transaction/ID/text()" equals "{@txId2}"                                          # WebAPICucumberHooks.checkXPathEquals(String,String)
    When I call "GET /repos/repo1/endTransaction?transactionId={@txId}"                                        # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/theirs/text()" equals "{@ObjectId|repo1|master}"                            # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/ours/text()" equals "{@ObjectId|repo1|@txId|master}"                        # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/ancestor/text()" equals "{@ObjectId|repo1|master~1}"                        # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/conflicts/text()" equals "1"                                                # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/change/text()" equals "CONFLICT"                                    # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/id/text()" equals "Points/Point.1"                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/ourvalue/text()" equals "0000000000000000000000000000000000000000"  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Merge/Feature/theirvalue/text()" equals "{@ObjectId|repo1|master:Points/Point.1}" # WebAPICucumberHooks.checkXPathEquals(String,String)
    Then I have committed "Point.1" on the "repo1" repo in the "@txId" transaction                             # WebAPICucumberHooks.I_have_committed(String,String,String)
    When I call "GET /repos/repo1/endTransaction?transactionId={@txId}"                                        # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/Transaction/ID/text()" equals "{@txId}"                                           # WebAPICucumberHooks.checkXPathEquals(String,String)
    When I call "GET /repos/repo1/cat?objectid={@ObjectId|repo1|master:Points/Point.1}"                        # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/feature/id/text()" equals "{@ObjectId|repo1|master:Points/Point.1}"               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/feature/attribute" 3 times                                  # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the response body should contain "StringProp1_1"                                                       # WebAPICucumberHooks.checkResponseTextContains(String)
    And the response body should contain "1000"                                                                # WebAPICucumberHooks.checkResponseTextContains(String)
    And the response body should contain "POINT (0 0)"                                                         # WebAPICucumberHooks.checkResponseTextContains(String)
@Commands @UpdateRef
Feature: UpdateRef
  The UpdateRef command allows a user to manually change the value of a ref and is supported through the "/repos/{repository}/updateref" endpoint
  The command must be executed using the HTTP GET method
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method issues 405 "Method not allowed" # UpdateRef.feature:6
    Given There is an empty repository named repo1                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/updateref"                         # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                 # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: UpdateRef outside of a repository issues 404 "Not found" # UpdateRef.feature:12
    Given There is an empty multirepo server                         # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/updateref?name=master"             # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"              # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"      # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling UpdateRef without a ref name issues a 500 status code                       # UpdateRef.feature:19
    Given There is an empty repository named repo1                                              # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/updateref"                                                    # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                    # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "Required parameter 'name' was not provided." # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling UpdateRef without a new value or delete specified issues a 500 status code                                                # UpdateRef.feature:25
    Given There is an empty repository named repo1                                                                                            # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/updateref?name=master"                                                                                      # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                                                                                  # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "Nothing specified to update with, must specify either deletion or new value to update to." # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling UpdateRef without a nonexistent name issues a 500 status code # UpdateRef.feature:31
    Given There is an empty repository named repo1                                # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/updateref?name=nonexistent&delete=true"         # WebAPICucumberHooks.callURL(String)
    Then the response status should be '500'                                      # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/error/text()" equals "Invalid name: nonexistent"     # WebAPICucumberHooks.checkXPathEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling UpdateRef with a new value updates the ref                              # UpdateRef.feature:37
    Given There is a default multirepo server                                               # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "GET /repos/repo1/updateref?name=master&newValue={@ObjectId|repo1|branch1}" # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                  # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/ChangedRef/name/text()" equals "refs/heads/master"             # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/ChangedRef/objectId/text()" equals "{@ObjectId|repo1|branch1}" # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the variable "{@ObjectId|repo1|master}" equals "{@ObjectId|repo1|branch1}"          # WebAPICucumberHooks.checkVariableEquals(String,String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo2 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Calling UpdateRef with the delete parameter deletes the ref                        # UpdateRef.feature:46
    Given There is a default multirepo server                                                  # WebAPICucumberHooks.setUpDefaultMultiRepo()
    When I call "GET /repos/repo1/updateref?name=branch1&delete=true"                          # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                                   # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                                     # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/ChangedRef/name/text()" equals "refs/heads/branch1"               # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xpath "/response/ChangedRef/objectId/text()" equals "{@ObjectId|repo1|master^1^2}" # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the variable "{@ObjectId|repo1|branch1}" equals ""                                     # WebAPICucumberHooks.checkVariableEquals(String,String)
@Commands @Version
Feature: Version
  The Version command allows a user to see the geogig version and is supported through the "/repos/{repository}/version" endpoint
  The command must be executed using the HTTP GET method
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Verify wrong HTTP method issues 405 "Method not allowed" # Version.feature:6
    Given There is an empty repository named repo1                   # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "PUT /repos/repo1/version"                           # WebAPICucumberHooks.callURL(String)
    Then the response status should be '405'                         # WebAPICucumberHooks.checkStatusCode(int)
    And the response allowed methods should be "GET"                 # WebAPICucumberHooks.checkResponseAllowedMethods(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Version outside of a repository issues 404 "Not found" # Version.feature:12
    Given There is an empty multirepo server                       # WebAPICucumberHooks.setUpEmptyMultiRepo()
    When I call "GET /repos/repo1/version"                         # WebAPICucumberHooks.callURL(String)
    Then the response status should be '404'                       # WebAPICucumberHooks.checkStatusCode(int)
    And the response ContentType should be "text/plain"            # WebAPICucumberHooks.checkContentType(String)
    And the response body should contain "Repository not found"    # WebAPICucumberHooks.checkResponseTextContains(String)
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Loading repository repo1 using FileRepositoryResolver
[main] INFO org.locationtech.geogig.web.MultiRepositoryProvider - Disposing repository {}. Cause: manually removed by remove() or invalidateAll()

  Scenario: Version returns geogig version details                               # Version.feature:19
    Given There is an empty repository named repo1                               # WebAPICucumberHooks.setUpEmptyRepo(String)
    When I call "GET /repos/repo1/version"                                       # WebAPICucumberHooks.callURL(String)
    Then the response status should be '200'                                     # WebAPICucumberHooks.checkStatusCode(int)
    And the xpath "/response/success/text()" equals "true"                       # WebAPICucumberHooks.checkXPathEquals(String,String)
    And the xml response should contain "/response/ProjectVersion" 1 times       # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/BuildTime" 1 times            # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/BuildUserName" 1 times        # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/BuildUserEmail" 1 times       # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/GitBranch" 1 times            # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/GitCommitID" 1 times          # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/GitCommitTime" 1 times        # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/GitCommitAuthorName" 1 times  # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/GitCommitAuthorEmail" 1 times # WebAPICucumberHooks.checkXPathCadinality(String,int)
    And the xml response should contain "/response/GitCommitMessage" 1 times     # WebAPICucumberHooks.checkXPathCadinality(String,int)

359 Scenarios (359 passed)
2805 Steps (2805 passed)
2m59.252s

Tests run: 3164, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 182.65 sec - in org.geogig.web.functional.RunFunctionalTest

Results :

Tests run: 3261, Failures: 0, Errors: 0, Skipped: 0

[JENKINS] Recording test results
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ geogig-web-api-functional-tests ---
[INFO] Building jar: /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/src/web/functional/target/geogig-web-api-functional-tests-1.1-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-jar-plugin:2.4:test-jar (default) @ geogig-web-api-functional-tests ---
[INFO] Building jar: /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/src/web/functional/target/geogig-web-api-functional-tests-1.1-SNAPSHOT-tests.jar
[INFO] 
[INFO] >>> maven-source-plugin:2.2.1:jar (attach-sources) > generate-sources @ geogig-web-api-functional-tests >>>
[INFO] 
[INFO] --- git-commit-id-plugin:2.2.2:revision (default) @ geogig-web-api-functional-tests ---
[WARNING] Failed to getClass for org.apache.maven.plugin.source.SourceJarMojo
[INFO] 
[INFO] <<< maven-source-plugin:2.2.1:jar (attach-sources) < generate-sources @ geogig-web-api-functional-tests <<<
[INFO] 
[INFO] --- maven-source-plugin:2.2.1:jar (attach-sources) @ geogig-web-api-functional-tests ---
[INFO] Building jar: /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/src/web/functional/target/geogig-web-api-functional-tests-1.1-SNAPSHOT-sources.jar
[INFO] 
[INFO] >>> maven-source-plugin:2.2.1:test-jar (attach-sources) > generate-sources @ geogig-web-api-functional-tests >>>
[INFO] 
[INFO] --- git-commit-id-plugin:2.2.2:revision (default) @ geogig-web-api-functional-tests ---
[WARNING] Failed to getClass for org.apache.maven.plugin.source.TestSourceJarMojo
[INFO] 
[INFO] <<< maven-source-plugin:2.2.1:test-jar (attach-sources) < generate-sources @ geogig-web-api-functional-tests <<<
[INFO] 
[INFO] --- maven-source-plugin:2.2.1:test-jar (attach-sources) @ geogig-web-api-functional-tests ---
[INFO] Building jar: /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/src/web/functional/target/geogig-web-api-functional-tests-1.1-SNAPSHOT-test-sources.jar
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ geogig-web-api-functional-tests ---
[INFO] Installing /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/src/web/functional/target/geogig-web-api-functional-tests-1.1-SNAPSHOT.jar to /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/.repository/org/locationtech/geogig/geogig-web-api-functional-tests/1.1-SNAPSHOT/geogig-web-api-functional-tests-1.1-SNAPSHOT.jar
[INFO] Installing /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/src/web/functional/pom.xml to /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/.repository/org/locationtech/geogig/geogig-web-api-functional-tests/1.1-SNAPSHOT/geogig-web-api-functional-tests-1.1-SNAPSHOT.pom
[INFO] Installing /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/src/web/functional/target/geogig-web-api-functional-tests-1.1-SNAPSHOT-tests.jar to /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/.repository/org/locationtech/geogig/geogig-web-api-functional-tests/1.1-SNAPSHOT/geogig-web-api-functional-tests-1.1-SNAPSHOT-tests.jar
[INFO] Installing /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/src/web/functional/target/geogig-web-api-functional-tests-1.1-SNAPSHOT-sources.jar to /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/.repository/org/locationtech/geogig/geogig-web-api-functional-tests/1.1-SNAPSHOT/geogig-web-api-functional-tests-1.1-SNAPSHOT-sources.jar
[INFO] Installing /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/src/web/functional/target/geogig-web-api-functional-tests-1.1-SNAPSHOT-test-sources.jar to /home/hudson/genie.geogig/.jenkins/jobs/geogig-1.1.x/workspace/.repository/org/locationtech/geogig/geogig-web-api-functional-tests/1.1-SNAPSHOT/geogig-web-api-functional-tests-1.1-SNAPSHOT-test-sources.jar
[JENKINS] Archiving disabled