Newer
Older
dub_jkp / source / dub / installation.d
/**
	Stuff related to installation.

	Copyright: © 2012 Matthias Dondorff
	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
	Authors: Matthias Dondorff
*/
module dub.installation;

import dub.utils;

import vibe.core.log;
import vibe.core.file;
import vibe.data.json;
import vibe.inet.url;

import std.array;
import std.exception;
import std.conv;


const bool PRETTY_JOURNAL = true;


/// Installation journal for later uninstallation, saved alongside the installation.
/// Example Json:
/// {
///		"version": 1,
///		"files": {
///			"file1": "typeoffile1",
///			...
///		}
///	}
class Journal {
	private const int Version = 1;
	
	enum Type {
		RegularFile,
		Directory,
		Alien
	}
	
	struct Entry {
		this( Type t, Path f ) { type = t; relFilename = f; }
		Type type;
		Path relFilename;
	}
	
	@property const(Entry[]) entries() const { return m_entries; }
	
	this() {  }
	
	/// Initializes a Journal from a previous installation.
	this(Path journalFile) {
		auto jsonJournal = jsonFromFile(journalFile);
		enforce(cast(int)jsonJournal["Version"] == Version, "Mismatched version: "~to!string(cast(int)jsonJournal["Version"]) ~ "vs. " ~to!string(Version));
		foreach(string file, type; jsonJournal["Files"])
			m_entries ~= Entry(to!Type(cast(string)type), Path(file));
	}
	
	void add(Entry e) { 
		foreach(Entry ent; entries) {
			if( e.relFilename == ent.relFilename ) {
				enforce(e.type == ent.type, "Duplicate('"~to!string(e.relFilename)~"'), different types: "~to!string(e.type)~" vs. "~to!string(ent.type));
				return;
			}
		}
		m_entries ~= e;
	}
	
	void save(Path p) {
		Json jsonJournal = serialize();
		Appender!(char[]) data;
		if(PRETTY_JOURNAL) toPrettyJson(data, jsonJournal);
		else toJson(data, jsonJournal);
		auto fileJournal = openFile(to!string(p), FileMode.CreateTrunc);
		scope(exit) fileJournal.close();
		fileJournal.write(cast(ubyte[])data.data());
	}
	
	private Json serialize() const {
		Json[string] files;
		foreach(Entry e; m_entries)
			files[to!string(e.relFilename)] = to!string(e.type);
		Json[string] json;
		json["Version"] = Version;
		json["Files"] = files;
		return Json(json);
	}
	
	private {
		Entry[] m_entries;
	}
}