Skip to content

Commit

Permalink
✨ Add option to use original commit message (#96)
Browse files Browse the repository at this point in the history
Fixes discussion #13
  • Loading branch information
Nef10 committed Sep 4, 2021
1 parent 98883f1 commit c03c7b0
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 7 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Here are all the inputs [repo-file-sync-action](https://github.com/BetaHuhn/repo
| `ASSIGNEES` | People to assign to the pull request | **No** | N/A |
| `COMMIT_PREFIX` | Prefix for commit message and pull request title | **No** | 🔄 |
| `COMMIT_BODY` | Commit message body. Will be appended to commit message, separated by two line returns. | **No** | '' |
| `ORIGINAL_MESSAGE` | Use original commit message instead. Only works if the file(s) where changed and the action was triggered by pushing a single commit. | **No** | false |
| `COMMIT_EACH_FILE` | Commit each file seperately | **No** | true |
| `GIT_EMAIL` | The e-mail address used to commit the synced files | **Only when using installation token** | the email of the PAT used |
| `GIT_USERNAME` | The username used to commit the synced files | **Only when using installation token** | the username of the PAT used |
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ inputs:
description: |
Overwrite any existing Sync PR with the new changes. Defaults to true
required: false
ORIGINAL_MESSAGE:
description: |
Re-use the original commit message for commits. Works only if the action is triggered by pushing one commit. Defaults to false
required: false
SKIP_PR:
description: |
Skips creating a Pull Request and pushes directly to the default branch. Defaults to false
Expand Down
5 changes: 5 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ try {
type: 'boolean',
default: false
}),
ORIGINAL_MESSAGE: getInput({
key: 'ORIGINAL_MESSAGE',
type: 'boolean',
default: false
}),
BRANCH_PREFIX: getInput({
key: 'BRANCH_PREFIX',
default: 'repo-sync/SOURCE_REPO_NAME'
Expand Down
55 changes: 54 additions & 1 deletion src/git.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { parse } = require('@putout/git-status-porcelain')
const core = require('@actions/core')
const github = require('@actions/github')
const { GitHub, getOctokitOptions } = require('@actions/github/lib/utils')
const { throttling } = require('@octokit/plugin-throttling')
const path = require('path')
Expand Down Expand Up @@ -127,6 +128,58 @@ class Git {
)
}

isOneCommitPush() {
return github.context.eventName === 'push' && github.context.payload.commits.length === 1
}

originalCommitMessage() {
return github.context.payload.commits[0].message
}

parseGitDiffOutput(string) { // parses git diff output and returns a dictionary mapping the file path to the diff output for this file
// split diff into separate entries for separate files. \ndiff --git should be a reliable way to detect the separation, as content of files is always indented
return `\n${ string }`.split('\ndiff --git').slice(1).reduce((resultDict, fileDiff) => {
const lines = fileDiff.split('\n')
const lastHeaderLineIndex = lines.findIndex((line) => line.startsWith('+++'))
const plainDiff = lines.slice(lastHeaderLineIndex + 1).join('\n').trim()
let filePath = ''
if (lines[lastHeaderLineIndex].startsWith('+++ b/')) { // every file except removed files
filePath = lines[lastHeaderLineIndex].slice(6) // remove '+++ b/'
} else { // for removed file need to use header line with filename before deletion
filePath = lines[lastHeaderLineIndex - 1].slice(6) // remove '--- a/'
}
return { ...resultDict, [filePath]: plainDiff }
}, {})
}

async getChangesFromLastCommit(source) { // gets array of git diffs for the source, which either can be a file or a dict
if (this.lastCommitChanges === undefined) {
const diff = await this.github.repos.compareCommits({
mediaType: {
format: 'diff'
},
owner: github.context.payload.repository.owner.name,
repo: github.context.payload.repository.name,
base: github.context.payload.before,
head: github.context.payload.after
})
this.lastCommitChanges = this.parseGitDiffOutput(diff.data)
}
if (source.endsWith('/')) {
return Object.keys(this.lastCommitChanges).filter((filePath) => filePath.startsWith(source)).reduce((result, key) => [ ...result, this.lastCommitChanges[key] ], [])
} else {
return this.lastCommitChanges[source] === undefined ? [] : [ this.lastCommitChanges[source] ]
}
}

async changes(destination) { // gets array of git diffs for the destination, which either can be a file or a dict
const output = await execCmd(
`git diff HEAD ${ destination }`,
this.workingDir
)
return Object.values(this.parseGitDiffOutput(output))
}

async hasChanges() {
const statusOutput = await execCmd(
`git status --porcelain`,
Expand All @@ -142,7 +195,7 @@ class Git {
message += `\n\n${ COMMIT_BODY }`
}
return execCmd(
`git commit -m "${ message }"`,
`git commit -m "${ message.replace(/"/g, '\\"') }"`,
this.workingDir
)
}
Expand Down
5 changes: 4 additions & 1 deletion src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,15 @@ const remove = async (src) => {
return fs.remove(src)
}

const arrayEquals = (array1, array2) => Array.isArray(array1) && Array.isArray(array2) && array1.length === array2.length && array1.every((value, i) => value === array2[i])

module.exports = {
forEach,
dedent,
addTrailingSlash,
pathIsDirectory,
execCmd,
copy,
remove
remove,
arrayEquals
}
19 changes: 14 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const core = require('@actions/core')
const fs = require('fs')

const Git = require('./git')
const { forEach, dedent, addTrailingSlash, pathIsDirectory, copy, remove } = require('./helpers')
const { forEach, dedent, addTrailingSlash, pathIsDirectory, copy, remove, arrayEquals } = require('./helpers')

const {
parseConfig,
Expand All @@ -14,7 +14,8 @@ const {
TMP_DIR,
SKIP_CLEANUP,
OVERWRITE_EXISTING_PR,
SKIP_PR
SKIP_PR,
ORIGINAL_MESSAGE
} = require('./config')

const run = async () => {
Expand Down Expand Up @@ -82,14 +83,15 @@ const run = async () => {
// Use different commit/pr message based on if the source is a directory or file
const directory = isDirectory ? 'directory' : ''
const otherFiles = isDirectory ? 'and copied all sub files/folders' : ''
const useOriginalCommitMessage = ORIGINAL_MESSAGE && git.isOneCommitPush() && arrayEquals(await git.getChangesFromLastCommit(file.source), await git.changes(file.dest))

const message = {
true: {
commit: `${ COMMIT_PREFIX } Synced local '${ file.dest }' with remote '${ file.source }'`,
commit: useOriginalCommitMessage ? git.originalCommitMessage() : `${ COMMIT_PREFIX } Synced local '${ file.dest }' with remote '${ file.source }'`,
pr: `Synced local ${ directory } <code>${ file.dest }</code> with remote ${ directory } <code>${ file.source }</code>`
},
false: {
commit: `${ COMMIT_PREFIX } Created local '${ file.dest }' from remote '${ file.source }'`,
commit: useOriginalCommitMessage ? git.originalCommitMessage() : `${ COMMIT_PREFIX } Created local '${ file.dest }' from remote '${ file.source }'`,
pr: `Created local ${ directory } <code>${ file.dest }</code> ${ otherFiles } from remote ${ directory } <code>${ file.source }</code>`
}
}
Expand Down Expand Up @@ -128,7 +130,14 @@ const run = async () => {
if (hasChanges === true) {
core.debug(`Creating commit for remaining files`)

await git.commit()
let useOriginalCommitMessage = ORIGINAL_MESSAGE && git.isOneCommitPush()
if (useOriginalCommitMessage) {
await forEach(item.files, async (file) => {
useOriginalCommitMessage = useOriginalCommitMessage && arrayEquals(await git.getChangesFromLastCommit(file.source), await git.changes(file.dest))
})
}

await git.commit(useOriginalCommitMessage ? git.originalCommitMessage() : undefined)
modified.push({
dest: git.workingDir
})
Expand Down

0 comments on commit c03c7b0

Please sign in to comment.