summaryrefslogtreecommitdiffstats
path: root/src/com/gitblit/utils/PatchFormatter.java
blob: 15c1f94073d1d53b6d366782566dbab8df59d380 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.gitblit.utils;

import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.revwalk.RevCommit;

import com.gitblit.Constants;

public class PatchFormatter extends DiffFormatter {

	private final OutputStream os;

	private PatchTouple currentTouple = null;

	Map<String, PatchTouple> changes = new HashMap<String, PatchTouple>();

	public PatchFormatter(OutputStream os) {
		super(os);
		this.os = os;
	}

	public void format(DiffEntry entry) throws IOException {
		currentTouple = new PatchTouple();
		changes.put(entry.getNewPath(), currentTouple);
		super.format(entry);
	}

	@Override
	protected void writeLine(final char prefix, final RawText text, final int cur) throws IOException {
		switch (prefix) {
		case '+':
			currentTouple.insertions++;
			break;
		case '-':
			currentTouple.deletions++;
			break;
		}
		super.writeLine(prefix, text, cur);
	}

	public String getPatch(RevCommit commit) {
		StringBuilder patch = new StringBuilder();
		// hard-code the mon sep 17 2001 date string.
		// I have no idea why that is there. it seems to be a constant.
		patch.append("From " + commit.getName() + " Mon Sep 17 00:00:00 2001" + "\n");
		patch.append("From: " + JGitUtils.getDisplayName(commit.getAuthorIdent()) + "\n");
		patch.append("Date: " + (new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z").format(new Date(commit.getCommitTime() * 1000l))) + "\n");
		patch.append("Subject: [PATCH] " + commit.getShortMessage() + "\n");
		patch.append("\n");
		patch.append("---");
		int maxPathLen = 0;
		int files = 0;
		int insertions = 0;
		int deletions = 0;
		for (String path : changes.keySet()) {
			if (path.length() > maxPathLen) {
				maxPathLen = path.length();
			}
			PatchTouple touple = changes.get(path);
			files++;
			insertions += touple.insertions;
			deletions += touple.deletions;
		}
		int columns = 60;
		int total = insertions + deletions;
		int unit = total / columns + (total % columns > 0 ? 1 : 0);
		if (unit == 0) {
			unit = 1;
		}
		for (String path : changes.keySet()) {
			PatchTouple touple = changes.get(path);
			patch.append("\n " + StringUtils.rightPad(path, maxPathLen, ' ') + " | " + StringUtils.leftPad("" + touple.total(), 4, ' ') + " " + touple.relativeScale(unit));
		}
		patch.append(MessageFormat.format("\n {0} files changed, {1} insertions(+), {2} deletions(-)\n\n", files, insertions, deletions));
		patch.append(os.toString());
		patch.append("\n--\n");
		patch.append(Constants.getRunningVersion());
		return patch.toString();
	}

	private class PatchTouple {
		int insertions = 0;
		int deletions = 0;

		int total() {
			return insertions + deletions;
		}

		String relativeScale(int unit) {
			int plus = (insertions / unit);
			int minus = (deletions / unit);
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < plus; i++) {
				sb.append('+');
			}
			for (int i = 0; i < minus; i++) {
				sb.append('-');
			}
			return sb.toString();
		}
	}
}