Skip to content

Commit

Permalink
Merge 9c38951 into 1e4f6a0
Browse files Browse the repository at this point in the history
  • Loading branch information
jackton1 committed Mar 17, 2023
2 parents 1e4f6a0 + 9c38951 commit 8a22e51
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 67 deletions.
54 changes: 31 additions & 23 deletions internal/types/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package types

import (
"bytes"
"fmt"
"os"
"regexp"
Expand Down Expand Up @@ -70,7 +71,7 @@ func (a *Action) GetData() error {

// WriteDocumentation write the table to the output file
func (a *Action) WriteDocumentation(inputTable, outputTable *strings.Builder) error {
var err error
var err error
input, err := os.ReadFile(a.OutputFileName)

if err != nil {
Expand All @@ -79,46 +80,53 @@ func (a *Action) WriteDocumentation(inputTable, outputTable *strings.Builder) er

var output []byte

hasInputsData, inputStartIndex, inputEndIndex := utils.HasBytesInBetween(
hasInputsData, inputStartIndexes, inputEndIndexes := utils.HasBytesInBetween(
input,
[]byte(internal.InputsHeader),
[]byte(internal.InputAutoDocStart),
[]byte(internal.InputAutoDocEnd),
)

inputsStr := strings.TrimSpace(fmt.Sprintf("%s\n\n%v", internal.InputsHeader, inputTable.String()))
output = input
inputsStr := strings.TrimSpace(inputTable.String())

if hasInputsData {
output = utils.ReplaceBytesInBetween(input, inputStartIndex, inputEndIndex, []byte(inputsStr))
} else {
re, err := regexp.Compile(fmt.Sprintf("(?m)^%s", internal.InputsHeader))
if err != nil {
return err
for i := 0; i < len(inputStartIndexes); i++ {
output = utils.ReplaceBytesInBetween(output, inputStartIndexes[i], inputEndIndexes[i], []byte(inputsStr))
}
output = re.ReplaceAll([]byte(input), []byte(inputsStr))
} else {
re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.InputsHeader))
output = re.ReplaceAllFunc(input, func(match []byte) []byte {
if bytes.HasPrefix(match, []byte(internal.InputsHeader)) {
return []byte(fmt.Sprintf("%s\n\n%v", internal.InputsHeader, inputsStr))
}
return match
})
}

hasOutputsData, outputStartIndex, outputEndIndex := utils.HasBytesInBetween(
hasOutputsData, outputStartIndexes, outputEndIndexes := utils.HasBytesInBetween(
output,
[]byte(internal.OutputsHeader),
[]byte(internal.OutputAutoDocStart),
[]byte(internal.OutputAutoDocEnd),
)

outputsStr := strings.TrimSpace(fmt.Sprintf("%s\n\n%v", internal.OutputsHeader, outputTable.String()))
outputsStr := strings.TrimSpace(outputTable.String())

if hasOutputsData {
output = utils.ReplaceBytesInBetween(output, outputStartIndex, outputEndIndex, []byte(outputsStr))
} else {
re, err := regexp.Compile(fmt.Sprintf("(?m)^%s", internal.OutputsHeader))
if err != nil {
return err
for i := 0; i < len(outputStartIndexes); i++ {
output = utils.ReplaceBytesInBetween(output, outputStartIndexes[i], outputEndIndexes[i], []byte(outputsStr))
}
output = re.ReplaceAll([]byte(output), []byte(outputsStr))
} else {
re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.OutputsHeader))
output = re.ReplaceAllFunc(output, func(match []byte) []byte {
if bytes.HasPrefix(match, []byte(internal.OutputsHeader)) {
return []byte(fmt.Sprintf("%s\n\n%v", internal.OutputsHeader, outputsStr))
}
return match
})
}

if len(output) > 0 {
if err = os.WriteFile(a.OutputFileName, output, 0666); err != nil {
cobra.CheckErr(err)
}
if err = os.WriteFile(a.OutputFileName, output, 0666); err != nil {
cobra.CheckErr(err)
}

return nil
Expand Down
80 changes: 46 additions & 34 deletions internal/types/reusable.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package types

import (
"bytes"
"fmt"
"os"
"regexp"
Expand Down Expand Up @@ -82,7 +83,7 @@ func (r *Reusable) GetData() error {

// WriteDocumentation write the table to the output file
func (r *Reusable) WriteDocumentation(inputTable, outputTable, secretsTable *strings.Builder) error {
var err error
var err error
input, err := os.ReadFile(r.OutputFileName)

if err != nil {
Expand All @@ -91,64 +92,75 @@ func (r *Reusable) WriteDocumentation(inputTable, outputTable, secretsTable *str

var output []byte

hasInputsData, inputStartIndex, inputEndIndex := utils.HasBytesInBetween(
hasInputsData, inputStartIndexes, inputEndIndexes := utils.HasBytesInBetween(
input,
[]byte(internal.InputsHeader),
[]byte(internal.InputAutoDocStart),
[]byte(internal.InputAutoDocEnd),
)

inputsStr := strings.TrimSpace(fmt.Sprintf("%s\n\n%v", internal.InputsHeader, inputTable.String()))
output = input
inputsStr := strings.TrimSpace(inputTable.String())

if hasInputsData {
output = utils.ReplaceBytesInBetween(input, inputStartIndex, inputEndIndex, []byte(inputsStr))
} else {
re, err := regexp.Compile(fmt.Sprintf("(?m)^%s", internal.InputsHeader))
if err != nil {
return err
for i := 0; i < len(inputStartIndexes); i++ {
output = utils.ReplaceBytesInBetween(output, inputStartIndexes[i], inputEndIndexes[i], []byte(inputsStr))
}
output = re.ReplaceAll([]byte(input), []byte(inputsStr))
} else {
re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.InputsHeader))
output = re.ReplaceAllFunc(input, func(match []byte) []byte {
if bytes.HasPrefix(match, []byte(internal.InputsHeader)) {
return []byte(fmt.Sprintf("%s\n\n%v", internal.InputsHeader, inputsStr))
}
return match
})
}

hasOutputsData, outputStartIndex, outputEndIndex := utils.HasBytesInBetween(
hasOutputsData, outputStartIndexes, outputEndIndexes := utils.HasBytesInBetween(
output,
[]byte(internal.OutputsHeader),
[]byte(internal.OutputAutoDocStart),
[]byte(internal.OutputAutoDocEnd),
)

outputsStr := strings.TrimSpace(fmt.Sprintf("%s\n\n%v", internal.OutputsHeader, outputTable.String()))

outputsStr := strings.TrimSpace(outputTable.String())
if hasOutputsData {
output = utils.ReplaceBytesInBetween(output, outputStartIndex, outputEndIndex, []byte(outputsStr))
} else {
re, err := regexp.Compile(fmt.Sprintf("(?m)^%s", internal.OutputsHeader))
if err != nil {
return err
for i := 0; i < len(outputStartIndexes); i++ {
output = utils.ReplaceBytesInBetween(output, outputStartIndexes[i], outputEndIndexes[i], []byte(outputsStr))
}
output = re.ReplaceAll([]byte(output), []byte(outputsStr))
} else {
re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.OutputsHeader))
output = re.ReplaceAllFunc(output, func(match []byte) []byte {
if bytes.HasPrefix(match, []byte(internal.OutputsHeader)) {
return []byte(fmt.Sprintf("%s\n\n%v", internal.OutputsHeader, outputsStr))
}
return match
})
}

hasSecretsData, secretsStartIndex, secretsEndIndex := utils.HasBytesInBetween(
hasSecretsData, secretsStartIndexes, secretsEndIndexes := utils.HasBytesInBetween(
output,
[]byte(internal.SecretsHeader),
[]byte(internal.SecretsAutoDocStart),
[]byte(internal.SecretsAutoDocEnd),
)

secretsStr := strings.TrimSpace(fmt.Sprintf("%s\n\n%v", internal.SecretsHeader, secretsTable.String()))

secretsStr := strings.TrimSpace(secretsTable.String())
if hasSecretsData {
output = utils.ReplaceBytesInBetween(output, secretsStartIndex, secretsEndIndex, []byte(secretsStr))
} else {
re, err := regexp.Compile(fmt.Sprintf("(?m)^%s", internal.SecretsHeader))
if err != nil {
return err
for i := 0; i < len(secretsStartIndexes); i++ {
output = utils.ReplaceBytesInBetween(output, secretsStartIndexes[i], secretsEndIndexes[i], []byte(secretsStr))
}
output = re.ReplaceAll([]byte(output), []byte(secretsStr))
} else {
re := regexp.MustCompile(fmt.Sprintf("(?m)^%s", internal.SecretsHeader))
output = re.ReplaceAllFunc(output, func(match []byte) []byte {
if bytes.HasPrefix(match, []byte(internal.SecretsHeader)) {
return []byte(fmt.Sprintf("%s\n\n%v", internal.SecretsHeader, secretsStr))
}
return match
})
}

if len(output) > 0 {
if err = os.WriteFile(r.OutputFileName, output, 0666); err != nil {
cobra.CheckErr(err)
}
if err = os.WriteFile(r.OutputFileName, output, 0666); err != nil {
cobra.CheckErr(err)
}

return nil
Expand Down
57 changes: 47 additions & 10 deletions internal/utils/bytes_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,36 @@ limitations under the License.
*/
package utils

import "bytes"
import (
"bytes"
"regexp"
)

func HasBytesInBetween(value, start, end []byte) (found bool, startIndex int, endIndex int) {
s := bytes.Index(value, start)
func HasBytesInBetween(value, start, end []byte) (found bool, startIndexes []int, endIndexes []int) {
startRegexp := regexp.MustCompile("(?m)^" + string(start))
endRegexp := regexp.MustCompile("(?m)^" + string(end))

if s == -1 {
return false, -1, -1
// Find all start and end indexes
for i := 0; i < len(value); i++ {
startLoc := startRegexp.FindIndex(value[i:])
endLoc := endRegexp.FindIndex(value[i:])
if len(startLoc) > 0 && len(endLoc) > 0 {
startIndex := startLoc[0] + i
endIndex := endLoc[1] + i

if startIndex < endIndex {
startIndexes = append(startIndexes, startIndex)
endIndexes = append(endIndexes, endIndex)
}
i += endIndex // skip the content between end and next start
}
}

e := bytes.Index(value, end)

if e == -1 {
return false, -1, -1
if len(startIndexes) == 0 || len(endIndexes) == 0 {
return false, nil, nil
}

return true, s, e + len(end)
return true, startIndexes, endIndexes
}

func ReplaceBytesInBetween(value []byte, startIndex int, endIndex int, new []byte) []byte {
Expand All @@ -43,3 +57,26 @@ func ReplaceBytesInBetween(value []byte, startIndex int, endIndex int, new []byt
w += copy(t[w:], value[endIndex:])
return t[0:w]
}

func ReplaceAllBytesBetween(value []byte, startToken []byte, endToken []byte, new []byte) []byte {
startIndex := bytes.Index(value, startToken)
endIndex := bytes.Index(value, endToken)
result := make([]byte, len(value))

// copy bytes before startToken to the result
copy(result, value[:startIndex])

for startIndex != -1 && endIndex != -1 {
// copy new bytes between startToken and endToken to the result
result = append(result, new...)

// copy bytes after endToken to the result
result = append(result, value[endIndex+len(endToken):]...)

// find the next startToken and endToken
startIndex = bytes.Index(result, startToken)
endIndex = bytes.Index(result, endToken)
}

return result
}
33 changes: 33 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,39 @@ Test text ## Inputs

## Inputs

<!-- AUTO-DOC-INPUT:START - Do not remove or modify this section -->

| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION |
|-----------------------------------|--------|----------|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| base_sha | string | false | | Specify a different base commit SHA<br>used for comparing changes |
| diff_relative | string | false | | Exclude changes outside the current directory<br> and show path names relative to<br> it. **NOTE:** This requires you to<br> specify the top level directory via<br>the `path` input. |
| dir_names | string | false | `"false"` | Output unique changed directories instead of<br> filenames. **NOTE:** This returns `.` for<br> changed files located in the root<br>of the project. |
| dir_names_max_depth | string | false | | Maximum depth of directories to output.<br> e.g `test/test1/test2` with max depth of<br>`2` returns `test/test1`. |
| fetch_depth | string | false | `"50"` | Depth of additional branch history fetched.<br> **NOTE**: This can be adjusted to<br>resolve errors with insufficient history. |
| files | string | false | | File and directory patterns to detect<br> changes using only these list of<br> file(s) (Defaults to the entire repo)<br> **NOTE:** Multiline file/directory patterns should not<br>include quotes. |
| files_from_source_file | string | false | | Source file(s) used to populate the<br>`files` input. |
| files_ignore | string | false | | Ignore changes to these file(s) **NOTE:**<br> Multiline file/directory patterns should not include<br>quotes. |
| files_ignore_from_source_file | string | false | | Source file(s) used to populate the<br>`files_ignore` input |
| files_ignore_separator | string | false | `"\n"` | Separator used to split the `files_ignore`<br>input |
| files_separator | string | false | `"\n"` | Separator used to split the `files`<br>input |
| include_all_old_new_renamed_files | string | false | `"false"` | Include `all_old_new_renamed_files` output. Note this can<br>generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501). |
| json | string | false | `"false"` | Output list of changed files in<br> a JSON formatted string which can<br>be used for matrix jobs. |
| json_raw_format | string | false | `"false"` | Output list of changed files in<br> a raw format which means that<br> the output will not be surrounded<br> by quotes and special characters will<br>not be escaped. |
| match_directories | string | false | `"true"` | Indicates whether to include match directories |
| old_new_files_separator | string | false | `" "` | Split character for old and new<br>renamed filename pairs. |
| old_new_separator | string | false | `","` | Split character for old and new<br>filename pairs. |
| output_dir | string | false | `".github/outputs"` | Directory to store output files. |
| path | string | false | `"."` | Specify a relative path under `$GITHUB_WORKSPACE`<br>to locate the repository. |
| quotepath | string | false | `"true"` | Use non ascii characters to match<br> files and output the filenames completely<br>verbatim by setting this to `false` |
| separator | string | false | `" "` | Split character for output strings |
| sha | string | false | | Specify a different commit SHA used<br>for comparing changes |
| since | string | false | | Get changed files for commits whose<br> timestamp is older than the given<br>time. |
| since_last_remote_commit | string | true | `"false"` | Use the last commit on the<br> remote branch as the `base_sha`. Defaults<br> to the last non merge commit<br> on the target branch for pull<br> request events and the previous remote<br> commit of the current branch for<br>push events. |
| until | string | false | | Get changed files for commits whose<br> timestamp is earlier than the given<br>time. |
| write_output_files | string | false | `"false"` | Write outputs to files in the<br>`.github/outputs` folder by default. |

<!-- AUTO-DOC-INPUT:END -->

------

## Inputs
Expand Down

0 comments on commit 8a22e51

Please sign in to comment.