Repository: jestjs/jest (TypeScript)

Issue:
Tests failing for mercurial changed files
## 🐛 Bug Report

Currently, when cloning straight from [the current version `master`](https://github.com/facebook/jest/tree/d051b0da359c5930ab4c3ea69fe5524266622c96) [the test for getting changed files in `hg` is failing](https://github.com/facebook/jest/blob/d051b0da359c5930ab4c3ea69fe5524266622c96/e2e/__tests__/jestChangedFiles.test.ts#L263-L369).

I'm running the latest version of `hg` (5.0.1) in an old Mac I have but the same happens in any of the other machines I've cloned jest into.

The error I get is due to the pattern we use to specify a `revset` returning an empty revision range.

```bash
    Command failed: hg status -amnu --rev min((!public() & ::.)+.)^ /var/folders/p0/0npmk50s57v5sgzb_s9z2xmc0000gn/T/jest-changed-files-test-dir /var/folders/p0/0npmk50s57v5sgzb_s9z2xmc0000gn/T/jest-changed-files-test-dir/nested-dir /var/folders/p0/0npmk50s57v5sgzb_s9z2xmc0000gn/T/jest-changed-files-test-dir/nested-dir/second-nested-dir
    abort: empty revision range

      at makeError (node_modules/execa/index.js:181:11)
```


Related PRs:
* https://github.com/facebook/jest/pull/7880
* https://github.com/facebook/jest/pull/8066
* https://github.com/facebook/jest/pull/5476


## To Reproduce

Steps to reproduce the behavior:

1. Clone `jest`
2. Install `hg`
3. Install dependencies
4. Run tests (`yarn test`)


## Expected behavior

The test linked above should pass since the `withAncestor` option should return both the current changes and the changes in the last commit. Currently, the pattern we use to specify a `revset` errors because the pattern specifies an empty range.

**I managed to solve this locally myself, by using `ancestors(.)::0` as the argument for `--revset`, but I'm not sure whether this solution covers all necessary edge-cases**. Since I don't use `mercurial` myself I thought it was better to open an issue and see what other mercurial users think of this solution. If this is a satisfactory solution I can open a PR as I already have these changes commited to [this branch](https://github.com/lucasfcosta/jest/tree/fix-withAncestor-hg-revset).


## Link to repl or repo (highly encouraged)

As per the `steps to reproduce` section, this repo is its own reproducible repo.


## Run `npx envinfo --preset jest`

Paste the results here:

```bash
  System:
    OS: macOS High Sierra 10.13.6
    CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
  Binaries:
    Node: 10.16.0 - ~/.nvm/versions/node/v10.16.0/bin/node
    Yarn: 1.15.0 - /usr/local/bin/yarn
    npm: 6.9.0 - ~/.nvm/versions/node/v10.16.0/bin/npm
```



Hints:
I have same problem.
```
$ git rev-parse HEAD
e3f4c65140f08a2ec81e5a8260704c1d201e33c1
```

```
  System:
    OS: macOS 10.15.1
    CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
  Binaries:
    Node: 12.13.0 - ~/.nvm/versions/node/v12.13.0/bin/node
    Yarn: 1.19.1 - /usr/local/bin/yarn
    npm: 6.12.0 - ~/.nvm/versions/node/v12.13.0/bin/npm
```

```
$ hg --version
Mercurial Distributed SCM (version 5.1.2)
```

```
 FAIL  e2e/__tests__/jestChangedFiles.test.ts (26.869s)
  ● gets changed files for hg

    abort: empty revision range

      334 |   });
      335 | 
    > 336 |   ({changedFiles: files} = await getChangedFilesForRoots(roots, {
          |                            ^
      337 |     withAncestor: true,
      338 |   }));
      339 |   // Returns files from current uncommitted state + the last commit

      at makeError (node_modules/execa/lib/error.js:58:11)
          at runMicrotasks (<anonymous>)
          at async Promise.all (index 0)
      at Object.<anonymous> (e2e/__tests__/jestChangedFiles.test.ts:336:28)

 FAIL  e2e/__tests__/onlyChanged.test.ts (93.791s)
  ● gets changed files for hg

    expect(received).toMatch(expected)

    Expected pattern: /PASS __tests__(\/|\\)file2.test.js/
    Received string:  "·
      ● Test suite failed to run·
        abort: empty revision range
    "

      299 | 
      300 |   ({stdout, stderr} = runJest(DIR, ['-o', '--changedFilesWithAncestor']));
    > 301 |   expect(stderr).toMatch(/PASS __tests__(\/|\\)file2.test.js/);
          |                  ^
      302 |   expect(stderr).toMatch(/PASS __tests__(\/|\\)file3.test.js/);
      303 | });
      304 | 

      at Object.toMatch (e2e/__tests__/onlyChanged.test.ts:301:18)

```
Yeah, they fail for me as well. I've never used mercurial, so I have no real point of reference here. Maybe @scotthovestadt can help?
@SimenB I'd be happy to open a PR if the solution I've described when I opened the issue is valid, but given that I'm not an SVN expert, I'd like to confirm before doing it:

> I managed to solve this locally myself, by using ancestors(.)::0 as the argument for --revset, but I'm not sure whether this solution covers all necessary edge-cases. Since I don't use mercurial myself I thought it was better to open an issue and see what other mercurial users think of this solution. If this is a satisfactory solution I can open a PR as I already have these changes commited to this branch.
I have absolutely no clue, unfortunately... Maybe @quark-zju knows?
This is mostly likely related to phase configuration. In Mercurial, the common workflow is that the "master" branch has public commits, and feature branches have "draft" commits.

I suspect all commits are "drafts" and there are commits that should be public but are not public in these cases. In that case, `hg phase --public master` will probably fix it.

I think the revset can be changed to:

    first(min(!public() & ::.)^+.^)

to work with incorrect phase setup (all commits are draft) while still being able to take advantage of phases to detect draft feature branch.

Explanation:

- `min(!public() & ::.)^`: This is the parent of the first commit of the feature branch, or an empty set if phases is not setup correctly.
- `first(x+y)`: This picks `x` if `x` is not empty, or `y` if `x` is empty.

Patch:
diff --git a/packages/jest-changed-files/src/hg.ts b/packages/jest-changed-files/src/hg.ts
--- a/packages/jest-changed-files/src/hg.ts
+++ b/packages/jest-changed-files/src/hg.ts
@@ -18,7 +18,7 @@ const adapter: SCMAdapter = {
 
     const args = ['status', '-amnu'];
     if (options.withAncestor) {
-      args.push('--rev', 'min((!public() & ::.)+.)^');
+      args.push('--rev', 'first(min(!public() & ::.)^+.^)');
     } else if (options.changedSince) {
       args.push('--rev', `ancestor(., ${options.changedSince})`);
     } else if (options.lastCommit === true) {


Test patch:
diff --git a/e2e/__tests__/jestChangedFiles.test.ts b/e2e/__tests__/jestChangedFiles.test.ts
--- a/e2e/__tests__/jestChangedFiles.test.ts
+++ b/e2e/__tests__/jestChangedFiles.test.ts
@@ -362,14 +362,6 @@ test('handles a bad revision for "changedSince", for git', async () => {
 });
 
 testIfHg('gets changed files for hg', async () => {
-  if (process.env.CI) {
-    // Circle and Travis have very old version of hg (v2, and current
-    // version is v4.2) and its API changed since then and not compatible
-    // any more. Changing the SCM version on CIs is not trivial, so we'll just
-    // skip this test and run it only locally.
-    return;
-  }
-
   // file1.txt is used to make a multi-line commit message
   // with `hg commit -l file1.txt`.
   // This is done to ensure that `changedFiles` only returns files