From 47644e49ca252441fcc3ae57f5a01e7fc579ba8c Mon Sep 17 00:00:00 2001
From: John Ericson <John.Ericson@Obsidian.Systems>
Date: Fri, 7 Aug 2020 17:05:14 +0000
Subject: [PATCH] Specialize `std::optional<StorePath>` so this is backwards
 compatible

While I am cautious to break parametricity, I think it's OK in this
cases---we're not about to try to do some crazy polymorphic protocol
anytime soon.
---
 src/libstore/remote-store.cc    | 14 ++++++++++++++
 src/libstore/worker-protocol.hh |  7 +++++++
 2 files changed, 21 insertions(+)

diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 96e0aabba..005415666 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -70,6 +70,20 @@ void write(const Store & store, Sink & out, const StorePath & storePath)
     out << store.printStorePath(storePath);
 }
 
+
+template<>
+std::optional<StorePath> read(const Store & store, Source & from, Phantom<std::optional<StorePath>> _)
+{
+	auto s = readString(from);
+    return s == "" ? std::optional<StorePath> {} : store.parseStorePath(s);
+}
+
+template<>
+void write(const Store & store, Sink & out, const std::optional<StorePath> & storePathOpt)
+{
+    out << (storePathOpt ? store.printStorePath(*storePathOpt) : "");
+}
+
 }
 
 
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index c50995d7c..b3576fbeb 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -90,6 +90,13 @@ std::optional<T> read(const Store & store, Source & from, Phantom<std::optional<
 template<typename T>
 void write(const Store & store, Sink & out, const std::optional<T> & optVal);
 
+/* Specialization which uses and empty string for the empty case, taking
+   advantage of the fact StorePaths always serialize to a non-empty string.
+   This is done primarily for backwards compatability, so that StorePath <=
+   std::optional<StorePath>, where <= is the compatability partial order.
+ */
+template<>
+void write(const Store & store, Sink & out, const std::optional<StorePath> & optVal);
 
 template<typename T>
 std::map<std::string, T> read(const Store & store, Source & from, Phantom<std::map<std::string, T>> _)