/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.env.repository;
import com.caucho.env.git.*;
import com.caucho.inject.Module;
import com.caucho.util.Alarm;
import com.caucho.util.L10N;
import com.caucho.vfs.*;
import java.io.*;
import java.util.*;
import java.util.logging.Logger;
/**
* Map of the current tags.
*/
@Module
public class RepositoryTagMap
{
private static final Logger log = Logger.getLogger(RepositoryTagMap.class.getName());
private static final L10N L = new L10N(RepositoryTagMap.class);
private final String _commitHash;
private final GitCommit _commit;
private final long _sequence;
private final GitTree _tree;
private final Map<String,RepositoryTagEntry> _tagMap;
public RepositoryTagMap()
{
_commitHash = "";
_commit = null;
_sequence = 0;
_tagMap
= Collections.unmodifiableMap(new HashMap<String,RepositoryTagEntry>());
_tree = null;
}
public RepositoryTagMap(AbstractRepository repository,
String commitHash,
boolean isValidate)
throws IOException
{
_commitHash = commitHash;
if (commitHash == null)
throw new NullPointerException();
// force loading and validation from backend
if (isValidate)
repository.validateHash(commitHash);
_commit = repository.readCommit(commitHash);
String sequence = _commit.get("sequence");
if (sequence != null)
_sequence = Long.parseLong(sequence);
else
_sequence = 1;
_tree = repository.readTree(_commit.getTree());
_tagMap = readTagMap(repository, _tree.getHash("tags"));
}
public RepositoryTagMap(AbstractRepository repository,
RepositoryTagMap parent,
Map<String,RepositoryTagEntry> tagMap)
throws IOException
{
_tagMap = Collections.unmodifiableMap(tagMap);
long now = Alarm.getCurrentTime();
if (parent.getSequence() < now)
_sequence = now;
else
_sequence = parent.getSequence() + 1;
TempStream os = new TempStream();
WriteStream out = new WriteStream(os);
writeTagMap(out);
out.close();
String tagHash;
InputStream is = os.getInputStream();
try {
tagHash = repository.addBlob(is);
} finally {
is.close();
}
_tree = new GitTree();
_tree.addBlob("tags", 0775, tagHash);
for (String key : tagMap.keySet()) {
RepositoryTagEntry entry = tagMap.get(key);
String sha1 = entry.getTagEntryHash();
String root = entry.getRoot();
_tree.addBlob(sha1, 0644, sha1);
GitType type = repository.getType(root);
if (type == GitType.BLOB)
_tree.addBlob(root, 0644, root);
else if (type == GitType.TREE)
_tree.addDir(root, root);
else
throw new IllegalStateException(L.l("'{0}' has an unknown type {1}",
root, type));
}
String treeHash = repository.addTree(_tree);
_commit = new GitCommit();
_commit.setTree(treeHash);
_commit.put("sequence", String.valueOf(_sequence));
_commitHash = repository.addCommit(_commit);
}
/**
* Returns the commit hash value of the tag map itself
*/
public String getCommitHash()
{
return _commitHash;
}
/**
* Returns the sequence
*/
public long getSequence()
{
return _sequence;
}
/**
* Returns the deployment's tag map.
*/
public Map<String,RepositoryTagEntry> getTagMap()
{
return _tagMap;
}
private Map<String,RepositoryTagEntry> readTagMap(AbstractRepository repository,
String sha1)
throws IOException
{
TreeMap<String,RepositoryTagEntry> map
= new TreeMap<String,RepositoryTagEntry>();
InputStream is = repository.openBlob(sha1);
try {
ReadStream in = Vfs.openRead(is);
String tag;
while ((tag = in.readLine()) != null) {
String entrySha1 = in.readLine();
RepositoryTagEntry entry = new RepositoryTagEntry(repository, entrySha1);
map.put(tag, entry);
}
} finally {
is.close();
}
return Collections.unmodifiableMap(map);
}
private void writeTagMap(WriteStream out)
throws IOException
{
for (Map.Entry<String,RepositoryTagEntry> entry : _tagMap.entrySet()) {
out.println(entry.getKey());
out.println(entry.getValue().getTagEntryHash());
}
}
/**
* @param oldTagMap
* @return
*/
public int compareTo(RepositoryTagMap oldTagMap)
{
if (getSequence() < oldTagMap.getSequence())
return -1;
else if (oldTagMap.getSequence() < getSequence())
return 1;
return getCommitHash().compareTo(oldTagMap.getCommitHash());
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[seq=" + _sequence + "," + _commitHash + "]";
}
}