Mercurial > hg4j
comparison src/org/tmatesoft/hg/internal/ChangelogEntryBuilder.java @ 618:7c0d2ce340b8
Refactor approach how content finds it way down to a commit revision
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 16 May 2013 19:46:13 +0200 |
parents | dd4f6311af52 |
children | 4e6179bde4fc |
comparison
equal
deleted
inserted
replaced
617:65c01508f002 | 618:7c0d2ce340b8 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 TMate Software Ltd | 2 * Copyright (c) 2012-2013 TMate Software Ltd |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or modify | 4 * This program is free software; you can redistribute it and/or modify |
5 * it under the terms of the GNU General Public License as published by | 5 * it under the terms of the GNU General Public License as published by |
6 * the Free Software Foundation; version 2 of the License. | 6 * the Free Software Foundation; version 2 of the License. |
7 * | 7 * |
14 * the terms of a license other than GNU General Public License | 14 * the terms of a license other than GNU General Public License |
15 * contact TMate Software at support@hg4j.com | 15 * contact TMate Software at support@hg4j.com |
16 */ | 16 */ |
17 package org.tmatesoft.hg.internal; | 17 package org.tmatesoft.hg.internal; |
18 | 18 |
19 import java.io.ByteArrayOutputStream; | |
19 import java.util.ArrayList; | 20 import java.util.ArrayList; |
20 import java.util.Collection; | 21 import java.util.Collection; |
21 import java.util.Collections; | 22 import java.util.Collections; |
22 import java.util.Iterator; | 23 import java.util.Iterator; |
23 import java.util.LinkedHashMap; | 24 import java.util.LinkedHashMap; |
24 import java.util.List; | 25 import java.util.List; |
25 import java.util.Map; | 26 import java.util.Map; |
27 import java.util.Map.Entry; | |
26 import java.util.TimeZone; | 28 import java.util.TimeZone; |
27 import java.util.Map.Entry; | |
28 | 29 |
30 import org.tmatesoft.hg.core.HgIOException; | |
29 import org.tmatesoft.hg.core.Nodeid; | 31 import org.tmatesoft.hg.core.Nodeid; |
32 import org.tmatesoft.hg.internal.DataSerializer.DataSource; | |
30 import org.tmatesoft.hg.util.Path; | 33 import org.tmatesoft.hg.util.Path; |
31 | 34 |
32 /** | 35 /** |
33 * | 36 * Builds changelog entry |
34 * @author Artem Tikhomirov | 37 * @author Artem Tikhomirov |
35 * @author TMate Software Ltd. | 38 * @author TMate Software Ltd. |
36 */ | 39 */ |
37 public class ChangelogEntryBuilder { | 40 public class ChangelogEntryBuilder implements DataSource { |
38 | 41 |
39 private String user; | 42 private String user; |
40 private List<Path> modifiedFiles; | 43 private List<Path> modifiedFiles; |
41 private final Map<String, String> extrasMap = new LinkedHashMap<String, String>(); | 44 private final Map<String, String> extrasMap = new LinkedHashMap<String, String>(); |
42 private Integer tzOffset; | 45 private Integer tzOffset; |
43 private Long csetTime; | 46 private Long csetTime; |
47 private Nodeid manifestRev; | |
48 private CharSequence comment; | |
44 | 49 |
45 public ChangelogEntryBuilder user(String username) { | 50 public ChangelogEntryBuilder user(String username) { |
46 user = username; | 51 user = username; |
47 return this; | 52 return this; |
48 } | 53 } |
87 csetTime = seconds; | 92 csetTime = seconds; |
88 tzOffset = timezoneOffset; | 93 tzOffset = timezoneOffset; |
89 return this; | 94 return this; |
90 } | 95 } |
91 | 96 |
97 public ChangelogEntryBuilder manifest(Nodeid manifestRevision) { | |
98 manifestRev = manifestRevision; | |
99 return this; | |
100 } | |
101 | |
102 public ChangelogEntryBuilder comment(CharSequence commentString) { | |
103 comment = commentString; | |
104 return this; | |
105 } | |
106 | |
107 public void serialize(DataSerializer out) throws HgIOException { | |
108 byte[] b = build(); | |
109 out.write(b, 0, b.length); | |
110 } | |
111 | |
112 public int serializeLength() { | |
113 return -1; | |
114 } | |
115 | |
116 public byte[] build() { | |
117 ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
118 final int LF = '\n'; | |
119 CharSequence extras = buildExtras(); | |
120 CharSequence files = buildFiles(); | |
121 byte[] manifestRevision = manifestRev.toString().getBytes(); | |
122 byte[] username = user().getBytes(EncodingHelper.getUTF8()); | |
123 out.write(manifestRevision, 0, manifestRevision.length); | |
124 out.write(LF); | |
125 out.write(username, 0, username.length); | |
126 out.write(LF); | |
127 final long csetDate = csetTime(); | |
128 byte[] date = String.format("%d %d", csetDate, csetTimezone(csetDate)).getBytes(); | |
129 out.write(date, 0, date.length); | |
130 if (extras.length() > 0) { | |
131 out.write(' '); | |
132 byte[] b = extras.toString().getBytes(); | |
133 out.write(b, 0, b.length); | |
134 } | |
135 out.write(LF); | |
136 byte[] b = files.toString().getBytes(); | |
137 out.write(b, 0, b.length); | |
138 out.write(LF); | |
139 out.write(LF); | |
140 byte[] cmt = comment.toString().getBytes(EncodingHelper.getUTF8()); | |
141 out.write(cmt, 0, cmt.length); | |
142 return out.toByteArray(); | |
143 } | |
144 | |
145 private CharSequence buildExtras() { | |
146 StringBuilder extras = new StringBuilder(); | |
147 for (Iterator<Entry<String, String>> it = extrasMap.entrySet().iterator(); it.hasNext();) { | |
148 final Entry<String, String> next = it.next(); | |
149 extras.append(encodeExtrasPair(next.getKey())); | |
150 extras.append(':'); | |
151 extras.append(encodeExtrasPair(next.getValue())); | |
152 if (it.hasNext()) { | |
153 extras.append('\00'); | |
154 } | |
155 } | |
156 return extras; | |
157 } | |
158 | |
159 private CharSequence buildFiles() { | |
160 StringBuilder files = new StringBuilder(); | |
161 if (modifiedFiles != null) { | |
162 Collections.sort(modifiedFiles); | |
163 for (Iterator<Path> it = modifiedFiles.iterator(); it.hasNext(); ) { | |
164 files.append(it.next()); | |
165 if (it.hasNext()) { | |
166 files.append('\n'); | |
167 } | |
168 } | |
169 } | |
170 return files; | |
171 } | |
172 | |
173 private final static CharSequence encodeExtrasPair(String s) { | |
174 if (s != null) { | |
175 return s.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r").replace("\00", "\\0"); | |
176 } | |
177 return s; | |
178 } | |
179 | |
92 private long csetTime() { | 180 private long csetTime() { |
93 if (csetTime != null) { | 181 if (csetTime != null) { |
94 return csetTime; | 182 return csetTime; |
95 } | 183 } |
96 return System.currentTimeMillis() / 1000; | 184 return System.currentTimeMillis() / 1000; |
100 if (tzOffset != null) { | 188 if (tzOffset != null) { |
101 return tzOffset; | 189 return tzOffset; |
102 } | 190 } |
103 return -(TimeZone.getDefault().getOffset(time) / 1000); | 191 return -(TimeZone.getDefault().getOffset(time) / 1000); |
104 } | 192 } |
105 | |
106 public byte[] build(Nodeid manifestRevision, String comment) { | |
107 String f = "%s\n%s\n%d %d %s\n%s\n\n%s"; | |
108 StringBuilder extras = new StringBuilder(); | |
109 for (Iterator<Entry<String, String>> it = extrasMap.entrySet().iterator(); it.hasNext();) { | |
110 final Entry<String, String> next = it.next(); | |
111 extras.append(encodeExtrasPair(next.getKey())); | |
112 extras.append(':'); | |
113 extras.append(encodeExtrasPair(next.getValue())); | |
114 if (it.hasNext()) { | |
115 extras.append('\00'); | |
116 } | |
117 } | |
118 StringBuilder files = new StringBuilder(); | |
119 if (modifiedFiles != null) { | |
120 for (Iterator<Path> it = modifiedFiles.iterator(); it.hasNext(); ) { | |
121 files.append(it.next()); | |
122 if (it.hasNext()) { | |
123 files.append('\n'); | |
124 } | |
125 } | |
126 } | |
127 final long date = csetTime(); | |
128 final int tz = csetTimezone(date); | |
129 return String.format(f, manifestRevision.toString(), user(), date, tz, extras, files, comment).getBytes(); | |
130 } | |
131 | |
132 private final static CharSequence encodeExtrasPair(String s) { | |
133 if (s != null) { | |
134 return s.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r").replace("\00", "\\0"); | |
135 } | |
136 return s; | |
137 } | |
138 } | 193 } |