Index: trunk/ppbgrestore/src/ppbgrestoreVersion.c
===================================================================
--- trunk/ppbgrestore/src/ppbgrestoreVersion.c	(revision 25972)
+++ trunk/ppbgrestore/src/ppbgrestoreVersion.c	(revision 25973)
@@ -1,7 +1,104 @@
 #include "ppbgrestore.h"
 
-void ppbgrestoreVersionPrint()
+#ifndef PPBGRESTORE_VERSION
+#error "PPBGRESTORE_VERSION is not set"
+#endif
+#ifndef PPBGRESTORE_BRANCH
+#error "PPBGRESTORE_BRANCH is not set"
+#endif
+#ifndef PPBGRESTORE_SOURCE
+#error "PPBGRESTORE_SOURCE is not set"
+#endif
+
+psString ppbgrestoreVersion(void)
 {
-    // XXX: TODO
-    printf("version 0.0\n");
+    char *value = NULL;
+    psStringAppend(&value, "%s@%s", PPBGRESTORE_BRANCH, PPBGRESTORE_VERSION);
+    return value;
 }
+
+psString ppbgrestoreSource(void)
+{
+    return psStringCopy(PPBGRESTORE_SOURCE);
+}
+
+psString ppbgrestoreVersionLong(void)
+{
+    psString version = ppbgrestoreVersion();  // Version, to return
+    psString source = ppbgrestoreSource(); // Source
+
+    psStringPrepend(&version, "ppbgrestore ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
+    return version;
+};
+
+bool ppbgrestoreVersionHeader(psMetadata *header)
+{
+#ifdef notyet
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "ppbgrestore at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    psphotVersionHeader(header);
+    psastroVersionHeader(header);
+    ppStatsVersionHeader(header);
+
+    psString version = ppbgrestoreVersion(); // ppbgrestore software version
+    psString source  = ppbgrestoreSource();  // ppbgrestore software source
+
+    psStringPrepend(&version, "ppbgrestore version: ");
+    psStringPrepend(&source, "ppbgrestore source: ");
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, source);
+
+    psFree(version);
+    psFree(source);
+#endif // notyet
+
+    return true;
+}
+
+
+void ppbgrestoreVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("ppbgrestore", PS_LOG_INFO, "ppbgrestore at %s", timeString);
+    psFree(timeString);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString psphot = psphotVersionLong(); // psphot version
+    psString ppbgrestore = ppbgrestoreVersionLong(); // ppbgrestore version
+
+    psLogMsg("ppbgrestore", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("ppbgrestore", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("ppbgrestore", PS_LOG_INFO, "%s", psphot);
+    psLogMsg("ppbgrestore", PS_LOG_INFO, "%s", ppbgrestore);
+
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(psphot);
+    psFree(ppbgrestore);
+
+    return;
+}
