From 37a6d38b2d2d8f4ba2c561800df73f2842db9cbb Mon Sep 17 00:00:00 2001
From: Michal Dorner <dorner.michal@gmail.com>
Date: Wed, 7 Apr 2021 22:32:59 +0200
Subject: [PATCH 1/4] Add ref input parameter

---
 action.yml    |  6 ++++++
 dist/index.js | 45 ++++++++++++++++++++++++++++-----------------
 src/git.ts    | 36 ++++++++++++++++++++++--------------
 src/main.ts   | 11 ++++++-----
 4 files changed, 62 insertions(+), 36 deletions(-)

diff --git a/action.yml b/action.yml
index b25aa5e..f8a96e1 100644
--- a/action.yml
+++ b/action.yml
@@ -9,6 +9,12 @@ inputs:
   working-directory:
     description: 'Relative path under $GITHUB_WORKSPACE where the repository was checked out.'
     required: false
+  ref:
+    description: |
+      Git reference (e.g. branch name) from which the changes will be detected.
+      This option is ignored if action is triggered by pull_request event.
+    default: ${{ github.ref }}
+    required: false
   base:
     description: |
       Git reference (e.g. branch name) against which the changes will be detected. Defaults to repository default branch (e.g. master).
diff --git a/dist/index.js b/dist/index.js
index 2090549..5843c32 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -3865,34 +3865,44 @@ async function getChangesOnHead() {
     return parseGitDiffOutput(output);
 }
 exports.getChangesOnHead = getChangesOnHead;
-async function getChangesSinceMergeBase(base, ref, initialFetchDepth) {
+async function getChangesSinceMergeBase(base, head, initialFetchDepth) {
     let baseRef;
+    let headRef;
     async function hasMergeBase() {
-        return (baseRef !== undefined && (await exec_1.default('git', ['merge-base', baseRef, ref], { ignoreReturnCode: true })).code === 0);
+        if (baseRef === undefined || headRef === undefined) {
+            return false;
+        }
+        return (await exec_1.default('git', ['merge-base', baseRef, headRef], { ignoreReturnCode: true })).code === 0;
     }
     let noMergeBase = false;
-    core.startGroup(`Searching for merge-base ${base}...${ref}`);
+    core.startGroup(`Searching for merge-base ${base}...${headRef}`);
     try {
         baseRef = await getFullRef(base);
+        headRef = await getFullRef(head);
         if (!(await hasMergeBase())) {
-            await exec_1.default('git', ['fetch', '--no-tags', `--depth=${initialFetchDepth}`, 'origin', base, ref]);
-            if (baseRef === undefined) {
-                baseRef = await getFullRef(base);
-                if (baseRef === undefined) {
-                    await exec_1.default('git', ['fetch', '--tags', '--depth=1', 'origin', base, ref], {
+            await exec_1.default('git', ['fetch', '--no-tags', `--depth=${initialFetchDepth}`, 'origin', base, head]);
+            if (baseRef === undefined || headRef === undefined) {
+                baseRef = baseRef !== null && baseRef !== void 0 ? baseRef : await getFullRef(base);
+                headRef = headRef !== null && headRef !== void 0 ? headRef : await getFullRef(head);
+                if (baseRef === undefined || headRef === undefined) {
+                    await exec_1.default('git', ['fetch', '--tags', '--depth=1', 'origin', base, head], {
                         ignoreReturnCode: true // returns exit code 1 if tags on remote were updated - we can safely ignore it
                     });
-                    baseRef = await getFullRef(base);
+                    baseRef = baseRef !== null && baseRef !== void 0 ? baseRef : await getFullRef(base);
+                    headRef = headRef !== null && headRef !== void 0 ? headRef : await getFullRef(head);
                     if (baseRef === undefined) {
                         throw new Error(`Could not determine what is ${base} - fetch works but it's not a branch or tag`);
                     }
+                    if (headRef === undefined) {
+                        throw new Error(`Could not determine what is ${head} - fetch works but it's not a branch or tag`);
+                    }
                 }
             }
             let depth = initialFetchDepth;
             let lastCommitCount = await getCommitCount();
             while (!(await hasMergeBase())) {
                 depth = Math.min(depth * 2, Number.MAX_SAFE_INTEGER);
-                await exec_1.default('git', ['fetch', `--deepen=${depth}`, 'origin', base, ref]);
+                await exec_1.default('git', ['fetch', `--deepen=${depth}`, 'origin', base, head]);
                 const commitCount = await getCommitCount();
                 if (commitCount === lastCommitCount) {
                     core.info('No more commits were fetched');
@@ -3910,10 +3920,10 @@ async function getChangesSinceMergeBase(base, ref, initialFetchDepth) {
     finally {
         core.endGroup();
     }
-    let diffArg = `${baseRef}...${ref}`;
+    let diffArg = `${baseRef}...${headRef}`;
     if (noMergeBase) {
         core.warning('No merge base found - change detection will use direct <commit>..<commit> comparison');
-        diffArg = `${baseRef}..${ref}`;
+        diffArg = `${baseRef}..${headRef}`;
     }
     // Get changes introduced on ref compared to base
     core.startGroup(`Change detection ${diffArg}`);
@@ -4690,6 +4700,7 @@ async function run() {
             process.chdir(workingDirectory);
         }
         const token = core.getInput('token', { required: false });
+        const ref = core.getInput('ref', { required: false });
         const base = core.getInput('base', { required: false });
         const filtersInput = core.getInput('filters', { required: true });
         const filtersYaml = isPathInput(filtersInput) ? getConfigFileContent(filtersInput) : filtersInput;
@@ -4700,7 +4711,7 @@ async function run() {
             return;
         }
         const filter = new filter_1.Filter(filtersYaml);
-        const files = await getChangedFiles(token, base, initialFetchDepth);
+        const files = await getChangedFiles(token, base, ref, initialFetchDepth);
         const results = filter.match(files);
         exportResults(results, listFiles);
     }
@@ -4720,7 +4731,7 @@ function getConfigFileContent(configPath) {
     }
     return fs.readFileSync(configPath, { encoding: 'utf8' });
 }
-async function getChangedFiles(token, base, initialFetchDepth) {
+async function getChangedFiles(token, base, ref, initialFetchDepth) {
     // if base is 'HEAD' only local uncommitted changes will be detected
     // This is the simplest case as we don't need to fetch more commits or evaluate current/before refs
     if (base === git.HEAD) {
@@ -4735,14 +4746,14 @@ async function getChangedFiles(token, base, initialFetchDepth) {
         return await git.getChangesInLastCommit();
     }
     else {
-        return getChangedFilesFromGit(base, initialFetchDepth);
+        return getChangedFilesFromGit(base, ref, initialFetchDepth);
     }
 }
-async function getChangedFilesFromGit(base, initialFetchDepth) {
+async function getChangedFilesFromGit(base, head, initialFetchDepth) {
     var _a;
     const defaultRef = (_a = github.context.payload.repository) === null || _a === void 0 ? void 0 : _a.default_branch;
     const beforeSha = github.context.eventName === 'push' ? github.context.payload.before : null;
-    const ref = git.getShortName(github.context.ref) ||
+    const ref = git.getShortName(head || github.context.ref) ||
         (core.warning(`'ref' field is missing in event payload - using current branch, tag or commit SHA`),
             await git.getCurrentRef());
     const baseRef = git.getShortName(base) || defaultRef;
diff --git a/src/git.ts b/src/git.ts
index ca652e8..ddf6ff3 100644
--- a/src/git.ts
+++ b/src/git.ts
@@ -54,30 +54,38 @@ export async function getChangesOnHead(): Promise<File[]> {
   return parseGitDiffOutput(output)
 }
 
-export async function getChangesSinceMergeBase(base: string, ref: string, initialFetchDepth: number): Promise<File[]> {
+export async function getChangesSinceMergeBase(base: string, head: string, initialFetchDepth: number): Promise<File[]> {
   let baseRef: string | undefined
+  let headRef: string | undefined
   async function hasMergeBase(): Promise<boolean> {
-    return (
-      baseRef !== undefined && (await exec('git', ['merge-base', baseRef, ref], {ignoreReturnCode: true})).code === 0
-    )
+    if (baseRef === undefined || headRef === undefined) {
+      return false
+    }
+    return (await exec('git', ['merge-base', baseRef, headRef], {ignoreReturnCode: true})).code === 0
   }
 
   let noMergeBase = false
-  core.startGroup(`Searching for merge-base ${base}...${ref}`)
+  core.startGroup(`Searching for merge-base ${base}...${headRef}`)
   try {
     baseRef = await getFullRef(base)
+    headRef = await getFullRef(head)
     if (!(await hasMergeBase())) {
-      await exec('git', ['fetch', '--no-tags', `--depth=${initialFetchDepth}`, 'origin', base, ref])
-      if (baseRef === undefined) {
-        baseRef = await getFullRef(base)
-        if (baseRef === undefined) {
-          await exec('git', ['fetch', '--tags', '--depth=1', 'origin', base, ref], {
+      await exec('git', ['fetch', '--no-tags', `--depth=${initialFetchDepth}`, 'origin', base, head])
+      if (baseRef === undefined || headRef === undefined) {
+        baseRef = baseRef ?? (await getFullRef(base))
+        headRef = headRef ?? (await getFullRef(head))
+        if (baseRef === undefined || headRef === undefined) {
+          await exec('git', ['fetch', '--tags', '--depth=1', 'origin', base, head], {
             ignoreReturnCode: true // returns exit code 1 if tags on remote were updated - we can safely ignore it
           })
-          baseRef = await getFullRef(base)
+          baseRef = baseRef ?? (await getFullRef(base))
+          headRef = headRef ?? (await getFullRef(head))
           if (baseRef === undefined) {
             throw new Error(`Could not determine what is ${base} - fetch works but it's not a branch or tag`)
           }
+          if (headRef === undefined) {
+            throw new Error(`Could not determine what is ${head} - fetch works but it's not a branch or tag`)
+          }
         }
       }
 
@@ -85,7 +93,7 @@ export async function getChangesSinceMergeBase(base: string, ref: string, initia
       let lastCommitCount = await getCommitCount()
       while (!(await hasMergeBase())) {
         depth = Math.min(depth * 2, Number.MAX_SAFE_INTEGER)
-        await exec('git', ['fetch', `--deepen=${depth}`, 'origin', base, ref])
+        await exec('git', ['fetch', `--deepen=${depth}`, 'origin', base, head])
         const commitCount = await getCommitCount()
         if (commitCount === lastCommitCount) {
           core.info('No more commits were fetched')
@@ -103,10 +111,10 @@ export async function getChangesSinceMergeBase(base: string, ref: string, initia
     core.endGroup()
   }
 
-  let diffArg = `${baseRef}...${ref}`
+  let diffArg = `${baseRef}...${headRef}`
   if (noMergeBase) {
     core.warning('No merge base found - change detection will use direct <commit>..<commit> comparison')
-    diffArg = `${baseRef}..${ref}`
+    diffArg = `${baseRef}..${headRef}`
   }
 
   // Get changes introduced on ref compared to base
diff --git a/src/main.ts b/src/main.ts
index de33bc2..c5b92de 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -19,6 +19,7 @@ async function run(): Promise<void> {
     }
 
     const token = core.getInput('token', {required: false})
+    const ref = core.getInput('ref', {required: false})
     const base = core.getInput('base', {required: false})
     const filtersInput = core.getInput('filters', {required: true})
     const filtersYaml = isPathInput(filtersInput) ? getConfigFileContent(filtersInput) : filtersInput
@@ -31,7 +32,7 @@ async function run(): Promise<void> {
     }
 
     const filter = new Filter(filtersYaml)
-    const files = await getChangedFiles(token, base, initialFetchDepth)
+    const files = await getChangedFiles(token, base, ref, initialFetchDepth)
     const results = filter.match(files)
     exportResults(results, listFiles)
   } catch (error) {
@@ -55,7 +56,7 @@ function getConfigFileContent(configPath: string): string {
   return fs.readFileSync(configPath, {encoding: 'utf8'})
 }
 
-async function getChangedFiles(token: string, base: string, initialFetchDepth: number): Promise<File[]> {
+async function getChangedFiles(token: string, base: string, ref: string, initialFetchDepth: number): Promise<File[]> {
   // if base is 'HEAD' only local uncommitted changes will be detected
   // This is the simplest case as we don't need to fetch more commits or evaluate current/before refs
   if (base === git.HEAD) {
@@ -70,18 +71,18 @@ async function getChangedFiles(token: string, base: string, initialFetchDepth: n
     core.info('Github token is not available - changes will be detected from PRs merge commit')
     return await git.getChangesInLastCommit()
   } else {
-    return getChangedFilesFromGit(base, initialFetchDepth)
+    return getChangedFilesFromGit(base, ref, initialFetchDepth)
   }
 }
 
-async function getChangedFilesFromGit(base: string, initialFetchDepth: number): Promise<File[]> {
+async function getChangedFilesFromGit(base: string, head: string, initialFetchDepth: number): Promise<File[]> {
   const defaultRef = github.context.payload.repository?.default_branch
 
   const beforeSha =
     github.context.eventName === 'push' ? (github.context.payload as Webhooks.WebhookPayloadPush).before : null
 
   const ref =
-    git.getShortName(github.context.ref) ||
+    git.getShortName(head || github.context.ref) ||
     (core.warning(`'ref' field is missing in event payload - using current branch, tag or commit SHA`),
     await git.getCurrentRef())
 

From 02eeef4973b96cab5ff4eb3cebba165690498a13 Mon Sep 17 00:00:00 2001
From: Michal Dorner <dorner.michal@gmail.com>
Date: Wed, 7 Apr 2021 22:41:22 +0200
Subject: [PATCH 2/4] Fix `undefined` instead of ref in log output

---
 dist/index.js | 10 +++++-----
 src/git.ts    |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/dist/index.js b/dist/index.js
index 5843c32..ea9a243 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -3875,21 +3875,21 @@ async function getChangesSinceMergeBase(base, head, initialFetchDepth) {
         return (await exec_1.default('git', ['merge-base', baseRef, headRef], { ignoreReturnCode: true })).code === 0;
     }
     let noMergeBase = false;
-    core.startGroup(`Searching for merge-base ${base}...${headRef}`);
+    core.startGroup(`Searching for merge-base ${base}...${head}`);
     try {
         baseRef = await getFullRef(base);
         headRef = await getFullRef(head);
         if (!(await hasMergeBase())) {
             await exec_1.default('git', ['fetch', '--no-tags', `--depth=${initialFetchDepth}`, 'origin', base, head]);
             if (baseRef === undefined || headRef === undefined) {
-                baseRef = baseRef !== null && baseRef !== void 0 ? baseRef : await getFullRef(base);
-                headRef = headRef !== null && headRef !== void 0 ? headRef : await getFullRef(head);
+                baseRef = baseRef !== null && baseRef !== void 0 ? baseRef : (await getFullRef(base));
+                headRef = headRef !== null && headRef !== void 0 ? headRef : (await getFullRef(head));
                 if (baseRef === undefined || headRef === undefined) {
                     await exec_1.default('git', ['fetch', '--tags', '--depth=1', 'origin', base, head], {
                         ignoreReturnCode: true // returns exit code 1 if tags on remote were updated - we can safely ignore it
                     });
-                    baseRef = baseRef !== null && baseRef !== void 0 ? baseRef : await getFullRef(base);
-                    headRef = headRef !== null && headRef !== void 0 ? headRef : await getFullRef(head);
+                    baseRef = baseRef !== null && baseRef !== void 0 ? baseRef : (await getFullRef(base));
+                    headRef = headRef !== null && headRef !== void 0 ? headRef : (await getFullRef(head));
                     if (baseRef === undefined) {
                         throw new Error(`Could not determine what is ${base} - fetch works but it's not a branch or tag`);
                     }
diff --git a/src/git.ts b/src/git.ts
index ddf6ff3..809249d 100644
--- a/src/git.ts
+++ b/src/git.ts
@@ -65,7 +65,7 @@ export async function getChangesSinceMergeBase(base: string, head: string, initi
   }
 
   let noMergeBase = false
-  core.startGroup(`Searching for merge-base ${base}...${headRef}`)
+  core.startGroup(`Searching for merge-base ${base}...${head}`)
   try {
     baseRef = await getFullRef(base)
     headRef = await getFullRef(head)

From 58ed00ec486f0395621febf08b0b667ad53d469e Mon Sep 17 00:00:00 2001
From: Michal Dorner <dorner.michal@gmail.com>
Date: Sun, 11 Apr 2021 20:49:05 +0200
Subject: [PATCH 3/4] Update README

---
 README.md     | 11 ++++++++---
 dist/index.js |  2 +-
 src/git.ts    |  2 +-
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index e78b1a0..1c963a8 100644
--- a/README.md
+++ b/README.md
@@ -66,13 +66,11 @@ For more scenarios see [examples](#examples) section.
 
 
 # What's New
+- Add `ref` input parameter
 - Add `list-files: csv` format
 - Configure matrix job to run for each folder with changes using `changes` output
 - Improved listing of matching files with `list-files: shell` and `list-files: escape` options
-- Support local changes
-- Fixed retrieval of all changes via Github API when there are 100+ changes
 - Paths expressions are now evaluated using [picomatch](https://github.com/micromatch/picomatch) library
-- Support workflows triggered by any event
 
 For more information see [CHANGELOG](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
 
@@ -111,6 +109,13 @@ For more information see [CHANGELOG](https://github.com/dorny/paths-filter/blob/
     # Default: repository default branch (e.g. master)
     base: ''
 
+    # Git reference (e.g. branch name) from which the changes will be detected.
+    # Useful when workflow can be triggered only on default branch (e.g. repository_dispatch event)
+    # but you want to get changes on different branch.
+    # This option is ignored if action is triggered by pull_request event.
+    # default: ${{ github.ref }}
+    ref:
+
     # How many commits are initially fetched from base branch.
     # If needed, each subsequent fetch doubles the
     # previously requested number of commits until the merge-base
diff --git a/dist/index.js b/dist/index.js
index ea9a243..5682bc6 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -3920,6 +3920,7 @@ async function getChangesSinceMergeBase(base, head, initialFetchDepth) {
     finally {
         core.endGroup();
     }
+    // Three dots '...' change detection - finds merge-base and compares against it
     let diffArg = `${baseRef}...${headRef}`;
     if (noMergeBase) {
         core.warning('No merge base found - change detection will use direct <commit>..<commit> comparison');
@@ -3929,7 +3930,6 @@ async function getChangesSinceMergeBase(base, head, initialFetchDepth) {
     core.startGroup(`Change detection ${diffArg}`);
     let output = '';
     try {
-        // Three dots '...' change detection - finds merge-base and compares against it
         output = (await exec_1.default('git', ['diff', '--no-renames', '--name-status', '-z', diffArg])).stdout;
     }
     finally {
diff --git a/src/git.ts b/src/git.ts
index 809249d..df56308 100644
--- a/src/git.ts
+++ b/src/git.ts
@@ -111,6 +111,7 @@ export async function getChangesSinceMergeBase(base: string, head: string, initi
     core.endGroup()
   }
 
+  // Three dots '...' change detection - finds merge-base and compares against it
   let diffArg = `${baseRef}...${headRef}`
   if (noMergeBase) {
     core.warning('No merge base found - change detection will use direct <commit>..<commit> comparison')
@@ -121,7 +122,6 @@ export async function getChangesSinceMergeBase(base: string, head: string, initi
   core.startGroup(`Change detection ${diffArg}`)
   let output = ''
   try {
-    // Three dots '...' change detection - finds merge-base and compares against it
     output = (await exec('git', ['diff', '--no-renames', '--name-status', '-z', diffArg])).stdout
   } finally {
     fixStdOutNullTermination()

From e8f370c19768d3e2df0498b0754683e6b3432b76 Mon Sep 17 00:00:00 2001
From: Michal Dorner <dorner.michal@gmail.com>
Date: Sun, 11 Apr 2021 20:58:42 +0200
Subject: [PATCH 4/4] Run PR workflow on PR to any branch

---
 .github/workflows/pull-request-verification.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/pull-request-verification.yml b/.github/workflows/pull-request-verification.yml
index 9d95fc3..b3f6952 100644
--- a/.github/workflows/pull-request-verification.yml
+++ b/.github/workflows/pull-request-verification.yml
@@ -4,7 +4,7 @@ on:
     paths-ignore: [ '*.md' ]
     branches:
       - master
-      - develop
+      - '**'
 
 jobs:
   build: