Make parts of jgit externalizable, so that they can be marshalled over the wire or onto disk, using formats from git mailing list. Signed-off-by: Nigel Magnay <nigel.magnay@xxxxxxxxx> --- .../src/org/spearce/jgit/lib/ObjectId.java | 31 ++++- .../src/org/spearce/jgit/transport/RefSpec.java | 77 +++++++---- .../org/spearce/jgit/transport/RemoteConfig.java | 142 +++++++++++++++++++- .../src/org/spearce/jgit/transport/URIish.java | 31 ++++- 4 files changed, 252 insertions(+), 29 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java index 52ce0d4..1385325 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectId.java @@ -38,6 +38,10 @@ package org.spearce.jgit.lib; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; import java.io.UnsupportedEncodingException; import org.spearce.jgit.util.NB; @@ -45,7 +49,7 @@ /** * A SHA-1 abstraction. */ -public class ObjectId extends AnyObjectId { +public class ObjectId extends AnyObjectId implements Externalizable { private static final ObjectId ZEROID; private static final String ZEROID_STR; @@ -56,6 +60,13 @@ } /** + * Empty constructor, for Externalizable. + */ + public ObjectId() { + // For Externalizable + } + + /** * Get the special all-null ObjectId. * * @return the all-null ObjectId, often used to stand-in for no object. @@ -269,4 +280,22 @@ protected ObjectId(final AnyObjectId src) { public ObjectId toObjectId() { return this; } + + public void readExternal(ObjectInput in) throws IOException, + ClassNotFoundException { + byte[] sha1 = new byte[20]; + in.read(sha1); + + w1 = NB.decodeInt32(sha1, 0); + w2 = NB.decodeInt32(sha1, 4); + w3 = NB.decodeInt32(sha1, 8); + w4 = NB.decodeInt32(sha1, 12); + w5 = NB.decodeInt32(sha1, 16); + } + + public void writeExternal(ObjectOutput out) throws IOException { + byte[] sha1 = new byte[20]; + copyRawTo(sha1, 0); + out.write(sha1); + } } diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/RefSpec.java b/org.spearce.jgit/src/org/spearce/jgit/transport/RefSpec.java index 521110b..0ee89b0 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/RefSpec.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/RefSpec.java @@ -37,6 +37,11 @@ package org.spearce.jgit.transport; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + import org.spearce.jgit.lib.Constants; import org.spearce.jgit.lib.Ref; @@ -46,7 +51,7 @@ * A ref specification provides matching support and limited rules to rewrite a * reference in one repository to another reference in another repository. */ -public class RefSpec { +public class RefSpec implements Externalizable { /** * Suffix for wildcard ref spec component, that indicate matching all refs * with specified prefix. @@ -109,30 +114,7 @@ public RefSpec() { * the specification is invalid. */ public RefSpec(final String spec) { - String s = spec; - if (s.startsWith("+")) { - force = true; - s = s.substring(1); - } - - final int c = s.indexOf(':'); - if (c == 0) { - s = s.substring(1); - if (isWildcard(s)) - throw new IllegalArgumentException("Invalid wildcards " + spec); - dstName = s; - } else if (c > 0) { - srcName = s.substring(0, c); - dstName = s.substring(c + 1); - if (isWildcard(srcName) && isWildcard(dstName)) - wildcard = true; - else if (isWildcard(srcName) || isWildcard(dstName)) - throw new IllegalArgumentException("Invalid wildcards " + spec); - } else { - if (isWildcard(s)) - throw new IllegalArgumentException("Invalid wildcards " + spec); - srcName = s; - } + initializeFromString(spec); } /** @@ -161,6 +143,42 @@ private RefSpec(final RefSpec p) { } /** + * Initialize the ref specification from a string. + * + * @param spec + * string describing the specification. + * @throws IllegalArgumentException + * the specification is invalid. + */ + private void initializeFromString(final String spec) { + srcName = null; + String s = spec; + if (s.startsWith("+")) { + force = true; + s = s.substring(1); + } + + final int c = s.indexOf(':'); + if (c == 0) { + s = s.substring(1); + if (isWildcard(s)) + throw new IllegalArgumentException("Invalid wildcards " + spec); + dstName = s; + } else if (c > 0) { + srcName = s.substring(0, c); + dstName = s.substring(c + 1); + if (isWildcard(srcName) && isWildcard(dstName)) + wildcard = true; + else if (isWildcard(srcName) || isWildcard(dstName)) + throw new IllegalArgumentException("Invalid wildcards " + spec); + } else { + if (isWildcard(s)) + throw new IllegalArgumentException("Invalid wildcards " + spec); + srcName = s; + } + } + + /** * Check if this specification wants to forcefully update the destination. * * @return true if this specification asks for updates without merge tests. @@ -421,4 +439,13 @@ public String toString() { } return r.toString(); } + + public void readExternal(ObjectInput in) throws IOException, + ClassNotFoundException { + initializeFromString(in.readUTF()); + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(toString()); + } } diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java b/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java index 5bbf664..22443b4 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/RemoteConfig.java @@ -38,10 +38,17 @@ package org.spearce.jgit.transport; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.spearce.jgit.lib.RepositoryConfig; @@ -53,7 +60,7 @@ * describing how refs should be transferred between this repository and the * remote repository. */ -public class RemoteConfig { +public class RemoteConfig implements Externalizable { private static final String SECTION = "remote"; private static final String KEY_URL = "url"; @@ -166,6 +173,17 @@ public RemoteConfig(final RepositoryConfig rc, final String remoteName) } /** + * Construct an empty remote config. + */ + public RemoteConfig() { + uris = new ArrayList<URIish>(); + fetch = new ArrayList<RefSpec>(); + push = new ArrayList<RefSpec>(); + uploadpack = DEFAULT_UPLOAD_PACK; + receivepack = DEFAULT_RECEIVE_PACK; + } + + /** * Update this remote's definition within the configuration. * * @param rc @@ -382,4 +400,126 @@ public TagOpt getTagOpt() { public void setTagOpt(final TagOpt option) { tagopt = option != null ? option : TagOpt.AUTO_FOLLOW; } + + private Map<String, Collection<String>> toMap() { + Map<String, Collection<String>> map = new HashMap<String, Collection<String>>(); + + if (uris.size() > 0) { + Collection<String> values = new ArrayList<String>(); + for (URIish uri : uris) { + values.add(uri.toPrivateString()); + } + map.put(KEY_URL, values); + } + + if (fetch.size() > 0) { + Collection<String> values = new ArrayList<String>(); + for (RefSpec refspec : fetch) { + values.add(refspec.toString()); + } + map.put(KEY_FETCH, values); + } + + if (push.size() > 0) { + Collection<String> values = new ArrayList<String>(); + for (RefSpec refspec : push) { + values.add(refspec.toString()); + } + map.put(KEY_PUSH, values); + } + + Collection<String> uploads = new ArrayList<String>(1); + uploads.add(uploadpack); + map.put(KEY_UPLOADPACK, uploads); + + Collection<String> receives = new ArrayList<String>(1); + receives.add(uploadpack); + map.put(KEY_RECEIVEPACK, receives); + + Collection<String> tag = new ArrayList<String>(1); + tag.add(tagopt.option()); + map.put(KEY_TAGOPT, tag); + + + return map; + } + + private void fromMap(Map<String, Collection<String>> map) + throws URISyntaxException { + for (Map.Entry<String, Collection<String>> entry : map.entrySet()) { + String key = entry.getKey(); + + if (key.equals(KEY_URL)) { + for (String value : entry.getValue()) { + uris.add(new URIish(value)); + } + } else if (key.equals(KEY_FETCH)) { + for (String value : entry.getValue()) { + fetch.add(new RefSpec(value)); + } + } else if (key.equals(KEY_PUSH)) { + for (String value : entry.getValue()) { + push.add(new RefSpec(value)); + } + } else if (key.equals(KEY_UPLOADPACK)) { + for (String value : entry.getValue()) { + uploadpack = value; + } + } else if (key.equals(KEY_RECEIVEPACK)) { + for (String value : entry.getValue()) { + receivepack = value; + } + } else if (key.equals(KEY_TAGOPT)) { + for (String value : entry.getValue()) { + tagopt = TagOpt.fromOption(value); + } + } + } + } + + public void readExternal(ObjectInput in) throws IOException, + ClassNotFoundException { + name = in.readUTF(); + int items = in.readInt(); + + Map<String, Collection<String>> map = new HashMap<String, Collection<String>>(); + for (int i = 0; i < items; i++) { + String key = in.readUTF(); + String value = in.readUTF(); + + Collection<String> values = map.get(key); + if (values == null) { + values = new ArrayList<String>(); + map.put(key, values); + } + + values.add(value); + } + + try { + fromMap(map); + } catch (URISyntaxException ex) { + throw new IOException("Problem reading RemoteConfig map"); + } + } + + public void writeExternal(ObjectOutput out) throws IOException { + Map<String, Collection<String>> map = toMap(); + + int size = 0; + + for (Map.Entry<String, Collection<String>> entry : map.entrySet()) { + size += entry.getValue().size(); + } + + out.writeUTF(name); + out.writeInt(size); + + for (Map.Entry<String, Collection<String>> entry : map.entrySet()) { + for (String value : entry.getValue()) { + out.writeUTF(entry.getKey()); + out.writeUTF(value); + } + } + } } diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/URIish.java b/org.spearce.jgit/src/org/spearce/jgit/transport/URIish.java index b86e00c..05e24b2 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/transport/URIish.java +++ b/org.spearce.jgit/src/org/spearce/jgit/transport/URIish.java @@ -38,6 +38,10 @@ package org.spearce.jgit.transport; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; import java.net.URISyntaxException; import java.net.URL; import java.util.regex.Matcher; @@ -49,7 +53,7 @@ * RFC 2396 URI's is that no URI encoding/decoding ever takes place. A space or * any special character is written as-is. */ -public class URIish { +public class URIish implements Externalizable { private static final Pattern FULL_URI = Pattern .compile("^(?:([a-z][a-z0-9+-]+)://(?:([^/]+?)(?::([^/]+?))?@)?(?:([^/]+?))?(?::(\\d+))?)?((?:[A-Za-z]:)?/.+)$"); @@ -75,7 +79,17 @@ * @throws URISyntaxException */ public URIish(String s) throws URISyntaxException { - s = s.replace('\\', '/'); + initializeFromString(s); + } + + /** + * Set fields from string based URI. + * + * @param s + * @throws URISyntaxException + */ + private void initializeFromString(String s) throws URISyntaxException { + s = s.replace('\\', '/'); Matcher matcher = FULL_URI.matcher(s); if (matcher.matches()) { scheme = matcher.group(1); @@ -357,4 +371,17 @@ private String format(final boolean includePassword) { return r.toString(); } + + public void readExternal(ObjectInput in) throws IOException, + ClassNotFoundException { + try { + initializeFromString(in.readUTF()); + } catch (URISyntaxException e) { + throw new IOException("Incorrect format URI"); + } + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(format(true)); + } } -- 1.6.0.2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html