summaryrefslogtreecommitdiff
path: root/patchid.go
diff options
context:
space:
mode:
Diffstat (limited to 'patchid.go')
-rw-r--r--patchid.go224
1 files changed, 120 insertions, 104 deletions
diff --git a/patchid.go b/patchid.go
index 72761a9..80f2cde 100644
--- a/patchid.go
+++ b/patchid.go
@@ -1,20 +1,16 @@
package gitpb
import (
- "bufio"
"bytes"
"crypto/sha1"
"encoding/hex"
"fmt"
- "io"
"os/exec"
"strings"
"go.wit.com/log"
)
-// git show 5b277e7686974d2195586d5f5b82838ee9ddb036 |git patch-id --stable
-// bf86be06af03b1a89ee155b214358362ec76f7b6 5b277e7686974d2195586d5f5b82838ee9ddb036
// forged patch: "working on ping pong"
// The --stable flag is an important detail. When you use it, git patch-id outputs two hashes:
// <stable_patch_id> <unstable_patch_id>
@@ -71,19 +67,53 @@ func (repo *Repo) FindPatchIdByHash(hash string) (string, error) {
return fields[0], nil
}
-// ComputePatchID calculates the patch ID for a given patch file's content.
-// It mimics the behavior of the `git patch-id` command by normalizing the
-// patch content before hashing.
-//
-// Normalization rules:
-// 1. It ignores all lines until the first "--- " line is encountered.
-// 2. It ignores diff headers (lines starting with "---", "+++", "diff --git", "index").
-// 3. For content lines ('+', '-', or ' '), it keeps the first character and
-// trims any trailing whitespace from the rest of the line before hashing.
-// 4. All other lines (like hunk headers "@@ ... @@") are ignored.
-func FindPatchIdByBytes(patchData io.Reader) (string, error) {
- scanner := bufio.NewScanner(patchData)
- var normalizedPatch bytes.Buffer
+func (repo *Repo) FindPatchIdFromGitAm(gitam []byte) (string, string, error) {
+ return FindPatchIdFromGitAm(gitam)
+}
+
+func FindPatchIdFromGitAm(gitam []byte) (string, string, error) {
+ // 1. Create the command.
+ cmd := exec.Command("git", "patch-id", "--stable")
+
+ // 2. Set the command's Stdin to a reader created from our string.
+ // This is the key change.
+ cmd.Stdin = strings.NewReader(string(gitam))
+
+ // 3. We need buffers to capture the command's output.
+ var stdout, stderr bytes.Buffer
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+
+ // 4. Run the command and wait for it to finish.
+ // cmd.Run() is a convenient wrapper around Start() and Wait().
+ err := cmd.Run()
+ if err != nil {
+ // Include stderr in the error message for better debugging.
+ return "", "", fmt.Errorf("git patch-id command failed: %w\nStderr: %s", err, stderr.String())
+ }
+
+ fields := strings.Fields(stdout.String())
+ if len(fields) != 2 {
+ return "", "", fmt.Errorf("git-patch-id produced empty output")
+ }
+
+ return fields[0], fields[1], nil
+}
+
+// computes the stable git patch-id from the output of git-am
+// doesn't work. it needs to add the SHA-1 parts together
+// cat WTF.2.diff | git patch-id --stable
+// go.wit.com/apps/utils/forged
+// git show 5b277e7686974d2195586d5f5b82838ee9ddb036 |git patch-id --stable
+// bf86be06af03b1a89ee155b214358362ec76f7b6 5b277e7686974d2195586d5f5b82838ee9ddb036
+// 73d73e12dcd727721253140ea68441dd0b824f8c 0000000000000000000000000000000000000000
+// 515792a0c4965b69f6b9e7f89e2f896148b03c97 0000000000000000000000000000000000000000
+// 1dd8b4a7d7d42a78fd1ff84dcc2ac87bc7318ee6 0000000000000000000000000000000000000000
+// 8478bad3e1f97818a68a014a8f30f1b2951b026b 0000000000000000000000000000000000000000
+func FindPatchIdFromGitAmBroken(gitAmData []byte) string {
+ var lines []string
+ scanner := NewLinesScanner(strings.Split(string(gitAmData), "\n"))
+ // var normalizedPatch bytes.Buffer
var inPatchBody bool
for scanner.Scan() {
@@ -91,7 +121,7 @@ func FindPatchIdByBytes(patchData io.Reader) (string, error) {
// The patch content officially starts at the first `---` line.
// This helps skip email headers in patches generated by `git format-patch`.
- if !inPatchBody && strings.HasPrefix(line, "---") {
+ if !inPatchBody && strings.HasPrefix(line, "diff ") {
inPatchBody = true
}
@@ -99,101 +129,87 @@ func FindPatchIdByBytes(patchData io.Reader) (string, error) {
continue
}
- // Skip headers and metadata lines
- if strings.HasPrefix(line, "---") ||
- strings.HasPrefix(line, "+++") ||
- strings.HasPrefix(line, "index") ||
- strings.HasPrefix(line, "diff --git") {
- continue
- }
-
- // Process only the actual content lines (context, addition, deletion)
- if len(line) > 0 && (line[0] == ' ' || line[0] == '+' || line[0] == '-') {
- // Keep the first character (' ', '+', or '-')
- firstChar := line[0]
- content := line[1:]
-
- // Trim trailing whitespace from the content part of the line
- trimmedContent := strings.TrimRight(content, " ")
-
- // Write the normalized line to our buffer for hashing
- normalizedPatch.WriteByte(firstChar)
- normalizedPatch.WriteString(trimmedContent)
- normalizedPatch.WriteByte('\n')
+ if line == "-- " {
+ break
}
- // All other lines (e.g., "@@ ... @@") are ignored.
- }
-
- if err := scanner.Err(); err != nil {
- return "", fmt.Errorf("error reading patch data: %w", err)
- }
+ lines = append(lines, line)
- // Calculate the SHA-1 hash of the normalized patch content
- hash := sha1.Sum(normalizedPatch.Bytes())
- patchID := hex.EncodeToString(hash[:])
-
- return patchID, nil
-}
+ /*
+ // Skip headers and metadata lines
+ if strings.HasPrefix(line, "---") ||
+ strings.HasPrefix(line, "+++") ||
+ strings.HasPrefix(line, "index") ||
+ strings.HasPrefix(line, "diff --git") {
+ continue
+ }
-/*
-// --- Example Usage ---
+ normalizedPatch.WriteString(line + "\n")
+ */
+ /*
+ // Process only the actual content lines (context, addition, deletion)
+ if len(line) > 0 && (line[0] == ' ' || line[0] == '+' || line[0] == '-') {
+ // Keep the first character (' ', '+', or '-')
+ firstChar := line[0]
+ content := line[1:]
-func main() {
- // Example 1: Using a string as input
- patchString := `
-From 2f42795678c7113f7437c04f56570c08b68850f4 Mon Sep 17 00:00:00 2001
-From: A Developer <[email protected]>
-Subject: [PATCH] Example change to demonstrate patch-id
+ // Trim trailing whitespace from the content part of the line
+ trimmedContent := strings.TrimRight(content, " ")
---- a/README.md
-+++ b/README.md
-@@ -1,3 +1,4 @@
- # My Project
-
--This is a sample project.
-+This is a sample project.
-+It has an additional line.
-`
- stringReader := strings.NewReader(patchString)
- patchID, err := ComputePatchID(stringReader)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error computing patch ID from string: %v\n", err)
- return
+ // Write the normalized line to our buffer for hashing
+ normalizedPatch.WriteByte(firstChar)
+ normalizedPatch.WriteString(trimmedContent)
+ normalizedPatch.WriteByte('\n')
+ }
+ // All other lines (e.g., "@@ ... @@") are ignored.
+ */
}
- fmt.Printf("Patch ID from string: %s\n", patchID)
- // Example 2: Reading from a file
- // Create a temporary patch file for demonstration
- patchContent := []byte(patchString)
- tmpfile, err := os.CreateTemp("", "example.*.patch")
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error creating temp file: %v\n", err)
- return
- }
- defer os.Remove(tmpfile.Name()) // clean up
+ // var fullhash [20]byte
- if _, err := tmpfile.Write(patchContent); err != nil {
- fmt.Fprintf(os.Stderr, "Error writing to temp file: %v\n", err)
- return
- }
- if err := tmpfile.Close(); err != nil {
- fmt.Fprintf(os.Stderr, "Error closing temp file: %v\n", err)
- return
+ var final string
+ for _, line := range lines {
+ if strings.HasPrefix(line, "---") {
+ // final += "---\n"
+ final += line + "\n"
+ continue
+ }
+ if strings.HasPrefix(line, "+++") {
+ // final += "+++\n"
+ final += line + "\n"
+ continue
+ }
+ if strings.HasPrefix(line, "index") {
+ // final += "index\n"
+ // final += line + "\n"
+ continue
+ }
+ if strings.HasPrefix(line, "@@") {
+ // final += "@@\n"
+ continue
+ }
+ if strings.HasPrefix(line, "diff --git") {
+ if len(final) != 0 {
+ hash := sha1.Sum([]byte(final))
+ // fullhash ?? hash
+ patchId := hex.EncodeToString(hash[:])
+ log.Info("partial hash", patchId)
+ }
+ log.Printf("%s", final)
+ // final += "diff --git\n"
+ final = line + "\n"
+ // final = ""
+ continue
+ }
+ final += line + "\n"
}
- // Open the file to pass to our function
- file, err := os.Open(tmpfile.Name())
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error opening temp file: %v\n", err)
- return
- }
- defer file.Close()
+ // final = strings.TrimSuffix(final, "\n")
- patchIDFromFile, err := ComputePatchID(file)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error computing patch ID from file: %v\n", err)
- return
- }
- fmt.Printf("Patch ID from file: %s\n", patchIDFromFile)
+ // Calculate the SHA-1 hash of the normalized patch content
+ // hash := sha1.Sum(normalizedPatch.Bytes())
+ hash := sha1.Sum([]byte(final))
+ patchID := hex.EncodeToString(hash[:])
+ // log.Printf("%s", final)
+ // log.Info(strings.Join(lines, "\n"))
+ return patchID
}
-*/