<pre style='margin:0'>
Dan Villiom Podlaski Christiansen (danchr) pushed a commit to branch master
in repository macports-ports.

</pre>
<p><a href="https://github.com/macports/macports-ports/commit/c2e7b865eaa8e7769810b0ee53eb94c3de1c61bd">https://github.com/macports/macports-ports/commit/c2e7b865eaa8e7769810b0ee53eb94c3de1c61bd</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new c2e7b865eaa watchman: update to 2022.08.08.00
</span>c2e7b865eaa is described below

<span style='display:block; white-space:pre;color:#808000;'>commit c2e7b865eaa8e7769810b0ee53eb94c3de1c61bd
</span>Author: Dan Villiom Podlaski Christiansen <danchr@macports.org>
AuthorDate: Mon Aug 22 13:41:04 2022 +0200

<span style='display:block; white-space:pre;color:#404040;'>    watchman: update to 2022.08.08.00
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    The recent update to folly broke building watchman. However, a simple
</span><span style='display:block; white-space:pre;color:#404040;'>    upgrade doesn't work, as they added yet another dependency to
</span><span style='display:block; white-space:pre;color:#404040;'>    something; their Eden SCM. Eden isn't in MacPorts, and I _really_
</span><span style='display:block; white-space:pre;color:#404040;'>    don't care about that one, so I disabled it -- which allowed pruning
</span><span style='display:block; white-space:pre;color:#404040;'>    the list of dependencies a bit. But they moved some code to rely on
</span><span style='display:block; white-space:pre;color:#404040;'>    it anyway, so I reverted those commits.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Since the update to Folly broke this, I added a comment to the port.
</span>---
 devel/folly/Portfile                               |   3 +
 sysutils/watchman/Portfile                         |  19 +-
 sysutils/watchman/files/revert-optionset-move.diff | 558 +++++++++++++++++++++
 3 files changed, 570 insertions(+), 10 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/folly/Portfile b/devel/folly/Portfile
</span><span style='display:block; white-space:pre;color:#808080;'>index ac4d37f837d..ca1a35638d8 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/devel/folly/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/folly/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -15,6 +15,9 @@ if {[string match *clang* ${configure.compiler}]} {
</span>     legacysupport.use_mp_libcxx yes
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+# NB: Facebook does not do API stabiilty, apparently, so please don't
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# upgrade without also upgrading its dependents, as listed by:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# port list rdepends:folly
</span> github.setup        facebook folly 2022.08.08.00 v
 revision            0
 checksums           rmd160  aaaf802ce3318fb2a666201779d8d254a53e6dec \
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/sysutils/watchman/Portfile b/sysutils/watchman/Portfile
</span><span style='display:block; white-space:pre;color:#808080;'>index f5cc21e1dc2..c54d131154c 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/sysutils/watchman/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/sysutils/watchman/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -7,8 +7,8 @@ PortGroup           boost 1.0
</span> PortGroup           rust 1.0
 PortGroup           compiler_blacklist_versions 1.0
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-github.setup        facebook watchman 2022.06.06.00 v
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-revision            3
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+github.setup        facebook watchman 2022.08.22.00 v
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+revision            0
</span> 
 categories          sysutils
 platforms           darwin
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -30,14 +30,12 @@ depends_build-append \
</span> depends_lib-append  port:pcre \
                     port:folly \
                     port:libevent \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    port:fizz \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    port:wangle \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    port:fbthrift \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    port:fb303 \
</span>                     port:google-glog \
                     port:${port_libfmt}
 
 configure.args-append \
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                    -DENABLE_EDEN_SUPPORT=NO \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    -DPython3_Development_FOUND=NO \
</span>                     -DBoost_INCLUDE_DIR=[boost::include_dir]
 
 configure.env-append \
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -45,7 +43,8 @@ configure.env-append \
</span>                     YARN_PATH=${prefix}/bin/yarn \
                     DESTDIR=${destroot}
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-patchfiles          cmake-rust-build-target.diff
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+patchfiles          cmake-rust-build-target.diff \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    revert-optionset-move.diff
</span> 
 post-patch {
     reinplace "s,/usr/bin,${prefix}," CMakeLists.txt
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -70,9 +69,9 @@ compiler.cxx_standard \
</span>                     2017
 
 checksums           ${distname}${extract.suffix}  \
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    rmd160  f172dae7f2d6f182bac266359ba14089af66ccd8 \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    sha256  d24548e0c4d5c692c15b5a8eaf46b02cb59d9fb228d611c31b6c8e81e7a4cb2e \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    size    3775957
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    rmd160  ccdc1f38d6a6d68c9bea0ef76267893ddec901ee \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    sha256  2a500e68317953b882276a979a3205c08a348c8910b9e33a4bcf606d0ab580f7 \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    size    3785713
</span> 
 
 cargo.crates \
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/sysutils/watchman/files/revert-optionset-move.diff b/sysutils/watchman/files/revert-optionset-move.diff
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..7fc73ed8c36
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/sysutils/watchman/files/revert-optionset-move.diff
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,558 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git CMakeLists.txt CMakeLists.txt
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- CMakeLists.txt
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ CMakeLists.txt
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -342,10 +342,10 @@ find_package(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ find_package(LibEvent REQUIRED)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ get_filename_component(LIBEVENT_LIBDIR "${LIBEVENT_LIB}" DIRECTORY)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ link_directories(${LIBEVENT_LIBDIR})
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-find_package(edencommon CONFIG REQUIRED)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ find_package(fmt CONFIG REQUIRED)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ find_package(folly CONFIG REQUIRED)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (ENABLE_EDEN_SUPPORT)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   find_package(fizz CONFIG REQUIRED)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   find_package(wangle CONFIG REQUIRED)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -450,7 +450,6 @@ target_link_libraries(third_party_deps I
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   gflags
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   ${Boost_LIBRARIES}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   fmt::fmt
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  edencommon::edencommon_utils
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ target_include_directories(third_party_deps INTERFACE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   ${FOLLY_INCLUDE_DIR}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -773,6 +772,7 @@ t_test(ignore watchman/test/BserTest.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #t_test(inmemoryview watchman/test/InMemoryViewTest.cpp)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ t_test(log watchman/test/LogTest.cpp)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ t_test(maputil watchman/test/MapUtilTest.cpp)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++t_test(optionset watchman/test/OptionSetTest.cpp)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ t_test(pendingcollection watchman/test/PendingCollectionTest.cpp)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Linking this test needs the targets graph to be cleaned up.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #t_test(perfsample watchman/test/PerfSampleTest.cpp)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git build/fbcode_builder/manifests/watchman build/fbcode_builder/manifests/watchman
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- build/fbcode_builder/manifests/watchman
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ build/fbcode_builder/manifests/watchman
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -13,7 +13,6 @@ builder = cmake
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ [dependencies]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ boost
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ cpptoml
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-edencommon
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fb303
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fbthrift
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git watchman/Client.cpp watchman/Client.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- watchman/Client.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ watchman/Client.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -23,17 +23,6 @@ namespace watchman {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ namespace {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-using namespace facebook::eden;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-ProcessNameCache& getProcessNameCache() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  static auto* pnc = new ProcessNameCache;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return *pnc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-ProcessNameHandle lookupProcessName(pid_t pid) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return getProcessNameCache().lookup(pid);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ constexpr size_t kResponseLogLimit = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly::Synchronized<std::unordered_set<UserClient*>> clients;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -220,10 +209,7 @@ void UserClient::create(std::unique_ptr<
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ UserClient::UserClient(PrivateBadge, std::unique_ptr<watchman_stream> stm)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    : Client{std::move(stm)},
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      since_{std::chrono::system_clock::now()},
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      peerPid_{this->stm->getPeerProcessID()},
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      peerName_{lookupProcessName(peerPid_)} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    : Client(std::move(stm)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   clients.wlock()->insert(this);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -260,13 +246,6 @@ std::vector<ClientDebugStatus> UserClien
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ClientDebugStatus UserClient::getDebugStatus() const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   ClientDebugStatus rv;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   rv.state = status_.getName();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (peerPid_) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    rv.peer.emplace();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    rv.peer->pid = peerPid_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    // May briefly, once, block on the ProcessNameCache thread.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    rv.peer->name = peerName_.get();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  rv.since = std::chrono::system_clock::to_time_t(since_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   return rv;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git watchman/Client.h watchman/Client.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- watchman/Client.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ watchman/Client.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -6,14 +6,9 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #pragma once
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <eden/common/utils/ProcessNameCache.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <fmt/format.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <chrono>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <deque>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <unordered_map>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/Clock.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/CommandRegistry.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/Logging.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -159,27 +154,12 @@ class ClientStatus {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   std::atomic<State> state_{THREAD_STARTING};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-struct PeerInfo : serde::Object {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  int32_t pid;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  std::string name;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  template <typename X>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  void map(X& x) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    x("pid", pid);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    x("name", name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct ClientDebugStatus : serde::Object {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   std::string state;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  std::optional<PeerInfo> peer;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  std::optional<int64_t> since;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   template <typename X>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   void map(X& x) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     x("state", state);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    x("peer", peer);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    x("since", since);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -234,10 +214,6 @@ class UserClient final : public Client {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   void clientThread() noexcept;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  const std::chrono::system_clock::time_point since_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  const pid_t peerPid_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  const facebook::eden::ProcessNameHandle peerName_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   ClientStatus status_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git watchman/CommandRegistry.h watchman/CommandRegistry.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- watchman/CommandRegistry.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ watchman/CommandRegistry.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -12,7 +12,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // TODO: We could avoid the Client dependency fi CommandHandler returned a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // json_ref response or error rather than taking a Client.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include "eden/common/utils/OptionSet.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include "watchman/OptionSet.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/Serde.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/thirdparty/jansson/jansson.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/watchman_preprocessor.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -101,7 +101,7 @@ using CommandHandler =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ using ResultPrinter = void (*)(const json_ref& result);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-struct CommandFlags : facebook::eden::OptionSet<CommandFlags, uint8_t> {};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++struct CommandFlags : OptionSet<CommandFlags, uint8_t> {};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ inline constexpr auto CMD_DAEMON = CommandFlags::raw(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ inline constexpr auto CMD_CLIENT = CommandFlags::raw(2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git watchman/OptionSet.h watchman/OptionSet.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+new file mode 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ watchman/OptionSet.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -0,0 +1,207 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * Copyright (c) Meta Platforms, Inc. and affiliates.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * This source code is licensed under the MIT license found in the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * LICENSE file in the root directory of this source tree.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#pragma once
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <assert.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <string.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <initializer_list>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <iosfwd>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <string>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <string_view>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <utility>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++namespace watchman {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * Typed wrapper around bit sets. Inspired by Swift's OptionSet.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * See OptionSetTest.cpp for example usage.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++template <typename Derived, typename Underlying>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++class OptionSet {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  static_assert(std::is_integral_v<Underlying>);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  using zero_t = struct zero_t***;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ public:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  using UnderlyingType = Underlying;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  using NameTable = std::initializer_list<std::pair<Derived, std::string_view>>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  constexpr OptionSet() = default;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Allows initialization from literal 0.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /* implicit */ constexpr OptionSet(zero_t) {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  ///* implicit */ constexpr OptionSet(Derived v) : value_{v.value_} {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /* implicit */ constexpr OptionSet(std::initializer_list<Derived> args) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    for (Derived v : args) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++      value_ |= v;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  constexpr static Derived raw(Underlying raw) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    Derived d;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    d.value_ = raw;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return d;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  explicit operator bool() const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return value_ != 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Returns the raw bits.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  Underlying asRaw() const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return value_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Returns true if every bit in `set` is set here too.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Alias for `containsAllOf`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  bool contains(Derived set) const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return containsAllOf(set);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Returns true if every bit in `set` is set here too.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  bool containsAllOf(Derived set) const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return (value_ & set.value_) == set.value_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Returns true if any bit in `set` in set here too.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  bool containsAnyOf(Derived set) const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return (value_ & set.value_) != 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Returns true if all bits in `set` are unset here.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  bool containsNoneOf(Derived set) const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return (value_ & set.value_) == 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Returns true if no bits are set.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  bool empty() const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return value_ == 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Turns on the specified bits.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  void set(Derived set) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    value_ |= set.value_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Clears the specified bits.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  void clear(Derived set) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    value_ &= ~set.value_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Returns a space-delimited string representing the names of each set bit.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * The name mapping is defined by `Derived::table`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  std::string format() const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    // TODO: It might be nice to move the implementation of this function behind
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    // a template on Raw to reduce the number of possible expansions. That would
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    // require some sort of constexpr mapping from Derived onto Raw. Perhaps
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    // that's as easy as asserting they have the same representation and casting
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    // pointers.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    constexpr const NameTable& table = Derived::table;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    if (empty() || std::empty(table)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++      return {};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    // Precompute the length to avoid multiple allocations.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    size_t length = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    for (auto [bit, name] : table) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++      // TODO: Should this assert bits are exact powers of two?
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++      if (containsAllOf(bit)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        if (length) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          length++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        length += name.size();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    std::string result(length, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    char* p = result.data();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    for (auto [bit, name] : table) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++      if (containsAllOf(bit)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        if (p != result.data()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++          *p++ = ' ';
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        memcpy(p, name.data(), name.size());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++        p += name.size();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    assert(static_cast<size_t>(p - result.data()) == length);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  template <typename... A>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  friend std::basic_ostream<A...>& operator<<(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++      std::basic_ostream<A...>& out,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++      const OptionSet& opts) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return out << opts.format();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  Derived& operator|=(Derived that) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    value_ |= that.value_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return static_cast<Derived&>(*this);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  Derived& operator&=(Derived that) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    value_ &= that.value_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return static_cast<Derived&>(*this);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Returns the union of both sets.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  constexpr friend Derived operator|(Derived lhs, Derived rhs) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return raw(lhs.value_ | rhs.value_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   * Returns the intersection of both sets.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++   */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  constexpr friend Derived operator&(Derived lhs, Derived rhs) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return raw(lhs.value_ & rhs.value_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  constexpr friend bool operator==(Derived lhs, Derived rhs) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return lhs.value_ == rhs.value_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  constexpr friend bool operator!=(Derived lhs, Derived rhs) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    return lhs.value_ != rhs.value_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  Underlying value_{};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++} // namespace watchman
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git watchman/PendingCollection.h watchman/PendingCollection.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- watchman/PendingCollection.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ watchman/PendingCollection.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -11,7 +11,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <folly/futures/Promise.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <chrono>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <condition_variable>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include "eden/common/utils/OptionSet.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include "watchman/OptionSet.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/thirdparty/libart/src/art.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/watchman_string.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -19,7 +19,7 @@ struct watchman_dir;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ namespace watchman {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-struct PendingFlags : facebook::eden::OptionSet<PendingFlags, uint8_t> {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++struct PendingFlags : OptionSet<PendingFlags, uint8_t> {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   using OptionSet::OptionSet;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   static const NameTable table;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git watchman/cmds/debug.cpp watchman/cmds/debug.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- watchman/cmds/debug.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ watchman/cmds/debug.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -5,10 +5,7 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  * LICENSE file in the root directory of this source tree.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <fmt/chrono.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <folly/String.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <folly/chrono/Conv.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <folly/system/Shell.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <unordered_map>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/Client.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include "watchman/InMemoryView.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -260,28 +257,6 @@ W_CMD_REG(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     CMD_DAEMON,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     w_cmd_realpath_root);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-namespace {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-std::string shellQuoteCommand(std::string_view command) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  std::vector<std::string> argv;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  folly::split('\0', command, argv);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  // Every argument in a command line is null-terminated. Remove the last, empty
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  // argument.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  if (argv.size() && argv.back().empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    argv.pop_back();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  for (auto& arg : argv) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    // TODO: shellQuote is not particularly good. It always brackets with ' and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    // does not handle non-printable characters. We should write our own.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-    arg = folly::shellQuote(arg);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-  return folly::join(' ', argv);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-} // namespace
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct DebugStatusCommand : PrettyCommand<DebugStatusCommand> {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   static constexpr std::string_view name = "debug-status";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -328,19 +303,7 @@ struct DebugStatusCommand : PrettyComman
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     fmt::print("CLIENTS\n-------\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     for (auto& client : response.clients) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      if (client.peer) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-        fmt::print(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-            "{}: {}\n", client.peer->pid, shellQuoteCommand(client.peer->name));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-        fmt::print("unknown peer\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      if (client.since) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-        fmt::print(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-            "  - since: {}\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-            std::chrono::system_clock::from_time_t(client.since.value()));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+       fmt::print("  - state: {}\n", client.state);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-      fmt::print("\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+     }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git watchman/test/OptionSetTest.cpp watchman/test/OptionSetTest.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+new file mode 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ watchman/test/OptionSetTest.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -0,0 +1,90 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * Copyright (c) Meta Platforms, Inc. and affiliates.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * This source code is licensed under the MIT license found in the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * LICENSE file in the root directory of this source tree.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include "watchman/OptionSet.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#include <folly/portability/GTest.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++using namespace watchman;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++namespace {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++struct ColorSet : OptionSet<ColorSet, uint8_t> {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  using OptionSet::OptionSet;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  static const NameTable table;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++constexpr inline auto CM_RED = ColorSet::raw(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++constexpr inline auto CM_GREEN = ColorSet::raw(2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++constexpr inline auto CM_BLUE = ColorSet::raw(4);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++const ColorSet::NameTable ColorSet::table = {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    {CM_RED, "RED"},
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    {CM_GREEN, "GREEN"},
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++    {CM_BLUE, "BLUE"},
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++} // namespace
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++TEST(OptionSet, initialization_from_zero) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  ColorSet set = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  set = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  // Does not compile:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  // set = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  // Does not compile:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  // int i = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  // set = i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++TEST(OptionSet, default_is_empty) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  ColorSet set;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_FALSE(set);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++TEST(OptionSet, assignment_operators) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  ColorSet set;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  set |= CM_RED;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ(CM_RED, set);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  set &= CM_GREEN;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ(ColorSet{}, set);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++TEST(OptionSet, format) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ("", ColorSet{}.format());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ("RED", CM_RED.format());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ("GREEN", CM_GREEN.format());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ("BLUE", CM_BLUE.format());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ("RED GREEN", (CM_RED | CM_GREEN).format());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ("GREEN BLUE", (CM_GREEN | CM_BLUE).format());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ("RED GREEN BLUE", (CM_RED | CM_GREEN | CM_BLUE).format());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++TEST(OptionSet, containsAllOf) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_TRUE((CM_RED | CM_GREEN).contains(CM_RED));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_FALSE((CM_RED | CM_GREEN).contains(CM_BLUE));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_FALSE((CM_RED | CM_GREEN).contains(CM_RED | CM_BLUE));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_TRUE((CM_RED | CM_GREEN).containsAllOf(CM_RED));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_FALSE((CM_RED | CM_GREEN).containsAllOf(CM_BLUE));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_FALSE((CM_RED | CM_GREEN).containsAllOf(CM_RED | CM_BLUE));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++TEST(OptionSet, intersect) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_FALSE(CM_RED & CM_BLUE);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_EQ(CM_GREEN, (CM_RED | CM_GREEN) & (CM_GREEN | CM_BLUE));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++TEST(OptionSet, containsAnyOf) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_TRUE((CM_RED | CM_GREEN).containsAnyOf(CM_GREEN | CM_BLUE));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_FALSE((CM_RED | CM_GREEN).containsAnyOf(CM_BLUE));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++TEST(OptionSet, containsNoneOf) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_FALSE((CM_RED | CM_GREEN).containsNoneOf(CM_GREEN | CM_BLUE));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++  EXPECT_TRUE(CM_RED.containsNoneOf(CM_GREEN | CM_BLUE));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++}
</span></pre><pre style='margin:0'>

</pre>