Merge branch 'master' into devTools
@@ -7,6 +7,8 @@ Obelisk provides an easy way to develop and deploy your [Reflex](https://github.
7- [Deploying](#deploying)
7- [Deploying](#deploying)
8 - [Locally](#locally)
8 - [Locally](#locally)
9 - [EC2](#ec2)
9 - [EC2](#ec2)
10+ - [From macOS](#from-macos)
11+ - [Deploying an updated version](#deploying-an-updated-version)
10- [Mobile](#mobile)
12- [Mobile](#mobile)
11 - [iOS](#ios)
13 - [iOS](#ios)
12 - [Android](#android)
14 - [Android](#android)
@@ -55,29 +57,13 @@ nix-shell -A obeliskEnvs.obelisk-command --run "cd lib/command && ghcid -c 'caba
57### Accessing private repositories
59### Accessing private repositories
58−To allow the Nix builder to access private git repositories, follow these steps:
61+To allow the Nix builder to access private git repositories, you must be set up
59−
62+to access them via SSH. Follow these steps depending on the platform you need
60−1. [Get set up to connect to GitHub with SSH](https://help.github.com/articles/connecting-to-github-with-ssh/)
65+- [GitHub](https://help.github.com/articles/connecting-to-github-with-ssh/)
61−1. [Create a GitHub personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/)
66+- [GitLab](https://docs.gitlab.com/ee/gitlab-basics/create-your-ssh-keys.html)
62−1. Set environment variables:
63− * NixOS: Add this to `/etc/nixos/configuration.nix`:
66− NIX_GITHUB_PRIVATE_USERNAME = "your-github-username";
67− NIX_GITHUB_PRIVATE_PASSWORD = "your-github-personal-access-token";
72− sudo launchctl setenv NIX_GITHUB_PRIVATE_USERNAME "your-github-username"
73− sudo launchctl setenv NIX_GITHUB_PRIVATE_PASSWORD "your-github-personal-access"
74− sudo launchctl stop org.nixos.nix-daemon
75− sudo launchctl start org.nixos.nix-daemon
77−1. `nix-env -i hub` OR `nix-env -iA nixos.gitAndTools.hub`
78−1. `hub clone yourusername/yourproject`
79− * NOTE: you must authenticate with hub at least once, because the `ob` command uses `hub` for authentication
80− #TODO: Make ob do this itself (either invoke hub automatically or not depend on hub)
82## Developing an Obelisk project
68## Developing an Obelisk project
@@ -154,7 +140,16 @@ ob deploy push
155`ob deploy push` will locally build your app and then transfer it, along with all the Nix package dependencies, via ssh to the EC2 instance. The backend will live in `/var/lib/backend`.
141`ob deploy push` will locally build your app and then transfer it, along with all the Nix package dependencies, via ssh to the EC2 instance. The backend will live in `/var/lib/backend`.
157−At this point you are done. Your app will be accessible at `${ROUTE}`.
143+At this point you are done. Your app will be accessible at `${ROUTE}`. The currently deployed version - the git commit hash of the source repo - can be found at `${ROUTE}/version`.
147+Deploying from macOS requires some extra setup:
149+- [Install nix-darwin](https://github.com/LnL7/nix-darwin)
150+- [Install docker](https://docs.docker.com/)
152+Running `ob deploy push` will give you additional setup instructions.
159### Deploying an updated version
154### Deploying an updated version
@@ -1,20 +1,13 @@
1{ system ? builtins.currentSystem
1{ system ? builtins.currentSystem
2, profiling ? false
2, profiling ? false
3, iosSdkVersion ? "10.2"
3, iosSdkVersion ? "10.2"
4+, __useLegacyCompilers ? false
6− getReflexPlatform = sys: import ./dep/reflex-platform { inherit iosSdkVersion; system = sys; enableLibraryProfiling = profiling; };
7+ cleanSource = builtins.filterSource (name: _: let baseName = builtins.baseNameOf name; in !(
7− reflex-platform = getReflexPlatform system;
8+ builtins.match "^\\.ghc\\.environment.*" baseName != null ||
8− inherit (reflex-platform) hackGet nixpkgs;
9+ baseName == "cabal.project.local"
9− pkgs = nixpkgs;
10+ ));
10−in with pkgs.haskell.lib; with pkgs.lib;
12− # TODO: Remove this after updating nixpkgs: https://github.com/NixOS/nixpkgs/issues/37750
13− justStaticExecutables' = drv: let
14− drv' = justStaticExecutables drv;
15− in if pkgs.stdenv.isDarwin
16− then removeConfigureFlag drv' "--ghc-option=-optl=-dead_strip"
19 commandRuntimeDeps = pkgs: with pkgs; [
12 commandRuntimeDeps = pkgs: with pkgs; [
@@ -24,102 +17,114 @@ let
27− #TODO: Upstream
20+ getReflexPlatform = getReflexPlatform' __useLegacyCompilers;
28− # Modify a Haskell package to add completion scripts for the given
21+ getReflexPlatform' = __useLegacyCompilers: sys: import ./dep/reflex-platform {
29− # executable produced by it. These completion scripts will be picked up
22+ inherit iosSdkVersion __useLegacyCompilers;
30− # automatically if the resulting derivation is installed, e.g. by
23+ system = sys;
31− # `nix-env -i`.
24+ enableLibraryProfiling = profiling;
32− addOptparseApplicativeCompletionScripts = exeName: pkg: overrideCabal pkg (drv: {
33− postInstall = (drv.postInstall or "") + ''
34− BASH_COMP_DIR="$out/share/bash-completion/completions"
35− mkdir -p "$BASH_COMP_DIR"
36− "$out/bin/${exeName}" --bash-completion-script "$out/bin/${exeName}" >"$BASH_COMP_DIR/ob"
38− ZSH_COMP_DIR="$out/share/zsh/vendor-completions"
26+ nixpkgsOverlays = [
39− mkdir -p "$ZSH_COMP_DIR"
27+ (self: super: {
40− "$out/bin/${exeName}" --zsh-completion-script "$out/bin/${exeName}" >"$ZSH_COMP_DIR/_ob"
28+ obeliskExecutableConfig = import ./lib/executable-config { nixpkgs = pkgs; filterGitSource = cleanSource; };
42− FISH_COMP_DIR="$out/share/fish/vendor_completions.d"
32+ haskellOverlays = [
43− mkdir -p "$FISH_COMP_DIR"
44− "$out/bin/${exeName}" --fish-completion-script "$out/bin/${exeName}" >"$FISH_COMP_DIR/ob.fish"
48− # The haskell environment used to build Obelisk itself, e.g. the 'ob' command
34+ # Fix misc upstream packages
49− ghcObelisk = reflex-platform.ghc.override {
35+ (self: super: let
50− overrides = composeExtensions defaultHaskellOverrides (self: super: {
36+ pkgs = self.callPackage ({ pkgs }: pkgs) {};
51− # Dynamic linking with split objects dramatically increases startup time (about 0.5 seconds on a decent machine with SSD)
37+ in {
52− obelisk-command = addOptparseApplicativeCompletionScripts "ob" (justStaticExecutables' super.obelisk-command);
38+ # Need 8.0.2 build support
53− });
39+ # PR: https://github.com/dmwit/universe/pull/33
40+ universe-template = self.callCabal2nix "universe-template" (pkgs.fetchFromGitHub {
41+ owner = "obsidiansystems";
43+ rev = "6a71119bfa5db2b9990a2491c941469ff8ef5d13";
44+ sha256 = "0z8smyainnlzcglv3dlx6x1n9j6d2jv48aa8f2421iayfkxg3js5";
56− # Development environments for obelisk packages.
48+ # Add obelisk packages
57− ghcObeliskEnvs = mapAttrs (n: v: reflex-platform.workOn ghcObelisk v) ghcObelisk;
49+ (self: super: let
50+ pkgs = self.callPackage ({ pkgs }: pkgs) {};
52+ obelisk-executable-config = pkgs.obeliskExecutableConfig.haskellPackage self;
53+ obelisk-executable-config-inject = pkgs.obeliskExecutableConfig.platforms.web.inject self;
59− fixUpstreamPkgs = self: super: {
55+ obelisk-asset-manifest = self.callCabal2nix "obelisk-asset-manifest" (hackGet ./lib/asset + "/manifest") {};
60− algebraic-graphs = pkgs.haskell.lib.doJailbreak
56+ obelisk-asset-serve-snap = self.callCabal2nix "obelisk-asset-serve-snap" (hackGet ./lib/asset + "/serve-snap") {};
61− (self.callCabal2nix "algebraic-graphs" (pkgs.fetchFromGitHub {
57+ obelisk-backend = self.callCabal2nix "obelisk-backend" (cleanSource ./lib/backend) {};
62− owner = "snowleopard";
58+ obelisk-cliapp = self.callCabal2nix "obelisk-cliapp" (cleanSource ./lib/cliapp) {};
63− repo = "alga";
59+ obelisk-command = self.callCabal2nix "obelisk-command" (cleanSource ./lib/command) {};
64− rev = "480a73137e9b38ad3f1bc2c628847953d2fb3e25";
60+ obelisk-frontend = self.callCabal2nix "obelisk-frontend" (cleanSource ./lib/frontend) {};
65− sha256 = "0dpwi5ffs88brl3lz51bwb004c6zm8ds8pkw1vzsg2a6aaiyhlzl";
61+ obelisk-run = self.callCabal2nix "obelisk-run" (cleanSource ./lib/run) {};
66− }) {});
62+ obelisk-route = self.callCabal2nix "obelisk-route" (cleanSource ./lib/route) {};
63+ obelisk-selftest = self.callCabal2nix "obelisk-selftest" (cleanSource ./lib/selftest) {};
64+ obelisk-snap-extras = self.callCabal2nix "obelisk-snap-extras" (cleanSource ./lib/snap-extras) {};
68− # Need deriveSomeUniverse
67+ (self: super: let
69− # PR: https://github.com/dmwit/universe/pull/32
68+ pkgs = self.callPackage ({ pkgs }: pkgs) {};
70− universe-template = self.callCabal2nix "universe-template" (pkgs.fetchFromGitHub {
69+ haskellLib = pkgs.haskell.lib;
71− owner = "obsidiansystems";
70+ #TODO: Upstream
72− repo = "universe";
71+ # Modify a Haskell package to add completion scripts for the given
73− rev = "5a2fc823caa4163411d7e41aa80e67cefb15944a";
72+ # executable produced by it. These completion scripts will be picked up
74− sha256 = "0ll2z0fh18z6x8jl8kbp7ldagwccz3wjmvrw1gw752z058n82yfa";
73+ # automatically if the resulting derivation is installed, e.g. by
75− } + /template) {};
74+ # `nix-env -i`.
76− };
75+ addOptparseApplicativeCompletionScripts = exeName: pkg: haskellLib.overrideCabal pkg (drv: {
76+ postInstall = (drv.postInstall or "") + ''
77+ BASH_COMP_DIR="$out/share/bash-completion/completions"
78+ mkdir -p "$BASH_COMP_DIR"
79+ "$out/bin/${exeName}" --bash-completion-script "$out/bin/${exeName}" >"$BASH_COMP_DIR/ob"
78− cleanSource = builtins.filterSource (name: _: let baseName = builtins.baseNameOf name; in !(
81+ ZSH_COMP_DIR="$out/share/zsh/vendor-completions"
79− builtins.match "^\\.ghc\\.environment.*" baseName != null ||
82+ mkdir -p "$ZSH_COMP_DIR"
80− baseName == "cabal.project.local"
83+ "$out/bin/${exeName}" --zsh-completion-script "$out/bin/${exeName}" >"$ZSH_COMP_DIR/_ob"
83− executableConfig = import ./lib/executable-config { nixpkgs = pkgs; filterGitSource = cleanSource; };
85+ FISH_COMP_DIR="$out/share/fish/vendor_completions.d"
86+ mkdir -p "$FISH_COMP_DIR"
87+ "$out/bin/${exeName}" --fish-completion-script "$out/bin/${exeName}" >"$FISH_COMP_DIR/ob.fish"
91+ # Dynamic linking with split objects dramatically increases startup time (about
92+ # 0.5 seconds on a decent machine with SSD), so we do `justStaticExecutables`.
93+ obelisk-command = haskellLib.overrideCabal
94+ (addOptparseApplicativeCompletionScripts "ob"
95+ (haskellLib.justStaticExecutables super.obelisk-command))
97+ buildTools = (drv.buildTools or []) ++ [ pkgs.buildPackages.makeWrapper ];
99+ ${drv.postFixup or ""}
100+ # Make `ob` reference its runtime dependencies.
101+ wrapProgram "$out"/bin/ob --prefix PATH : ${pkgs.lib.makeBinPath (commandRuntimeDeps pkgs)}
104+ obelisk-selftest = haskellLib.justStaticExecutables super.obelisk-selftest;
85− addLibs = self: super: {
107+ ];
86− obelisk-asset-manifest = self.callCabal2nix "obelisk-asset-manifest" (hackGet ./lib/asset + "/manifest") {};
87− obelisk-asset-serve-snap = self.callCabal2nix "obelisk-asset-serve-snap" (hackGet ./lib/asset + "/serve-snap") {};
88− obelisk-backend = self.callCabal2nix "obelisk-backend" (cleanSource ./lib/backend) {};
89− obelisk-cliapp = self.callCabal2nix "obelisk-cliapp" (cleanSource ./lib/cliapp) {};
90− obelisk-command = (self.callCabal2nix "obelisk-command" (cleanSource ./lib/command) {}).overrideAttrs
92− buildInputs = drv.buildInputs ++ [ pkgs.makeWrapper ];
94− ${drv.postInstall or ""}
96− cp -r ${./migration} $out/migration;
99− ${drv.postFixup or ""}
100− # Make `ob` reference its runtime dependencies.
101− wrapProgram "$out"/bin/ob --prefix PATH : ${pkgs.lib.makeBinPath (commandRuntimeDeps pkgs)}
104− obelisk-executable-config = executableConfig.haskellPackage self;
105− obelisk-executable-config-inject = executableConfig.platforms.web.inject self;
106− obelisk-frontend = self.callCabal2nix "obelisk-frontend" (cleanSource ./lib/frontend) {};
107− obelisk-migration = self.callCabal2nix "obelisk-migration" (cleanSource ./lib/migration) {};
108− obelisk-run = self.callCabal2nix "obelisk-run" (cleanSource ./lib/run) {};
109− obelisk-route = self.callCabal2nix "obelisk-route" (cleanSource ./lib/route) {};
110− obelisk-selftest = self.callCabal2nix "obelisk-selftest" (cleanSource ./lib/selftest) {};
111− obelisk-snap = self.callCabal2nix "obelisk-snap" (cleanSource ./lib/snap) {};
112− obelisk-snap-extras = self.callCabal2nix "obelisk-snap-extras" (cleanSource ./lib/snap-extras) {};
110+ reflex-platform = getReflexPlatform' false system;
111+ inherit (reflex-platform) hackGet nixpkgs;
114+ # The haskell environment used to build Obelisk itself, e.g. the 'ob' command
115+ ghcObelisk = reflex-platform.ghc;
117+ # Development environments for obelisk packages.
118+ ghcObeliskEnvs = pkgs.lib.mapAttrs (n: v: reflex-platform.workOn ghcObelisk v) ghcObelisk;
115 inherit (import ./lib/asset/assets.nix { inherit nixpkgs; }) mkAssets;
120 inherit (import ./lib/asset/assets.nix { inherit nixpkgs; }) mkAssets;
117− defaultHaskellOverrides = composeExtensions fixUpstreamPkgs addLibs;
119−with pkgs.lib;
122+ haskellLib = pkgs.haskell.lib;
121 inherit reflex-platform;
125 inherit reflex-platform;
122 inherit (reflex-platform) nixpkgs pinBuildInputs;
126 inherit (reflex-platform) nixpkgs pinBuildInputs;
127+ inherit (nixpkgs) lib;
123 pathGit = ./.; # Used in CI by the migration graph hash algorithm to correctly ignore files.
128 pathGit = ./.; # Used in CI by the migration graph hash algorithm to correctly ignore files.
124 path = reflex-platform.filterGit ./.;
129 path = reflex-platform.filterGit ./.;
125 obelisk = ghcObelisk;
130 obelisk = ghcObelisk;
@@ -133,7 +138,7 @@ rec {
134 PATH="${command}/bin:$PATH"
139 PATH="${command}/bin:$PATH"
135 export OBELISK_IMPL="${hackGet ./.}"
140 export OBELISK_IMPL="${hackGet ./.}"
136− "${justStaticExecutables' ghcObelisk.obelisk-selftest}/bin/obelisk-selftest" "$@"
141+ "${ghcObelisk.obelisk-selftest}/bin/obelisk-selftest" +RTS -N -RTS "$@"
138 #TODO: Why can't I build ./skeleton directly as a derivation? `nix-build -E ./.` doesn't work
143 #TODO: Why can't I build ./skeleton directly as a derivation? `nix-build -E ./.` doesn't work
139 skeleton = pkgs.runCommand "skeleton" {
144 skeleton = pkgs.runCommand "skeleton" {
@@ -141,26 +146,24 @@ rec {
142 ln -s "$dir" "$out"
147 ln -s "$dir" "$out"
144− nullIfAbsent = p: if pathExists p then p else null;
149+ nullIfAbsent = p: if lib.pathExists p then p else null;
145− haskellOverrides = addLibs;
146 #TODO: Avoid copying files within the nix store. Right now, obelisk-asset-manifest-generate copies files into a big blob so that the android/ios static assets can be imported from there; instead, we should get everything lined up right before turning it into an APK, so that copies, if necessary, only exist temporarily.
150 #TODO: Avoid copying files within the nix store. Right now, obelisk-asset-manifest-generate copies files into a big blob so that the android/ios static assets can be imported from there; instead, we should get everything lined up right before turning it into an APK, so that copies, if necessary, only exist temporarily.
147 processAssets = { src, packageName ? "obelisk-generated-static", moduleName ? "Obelisk.Generated.Static" }: pkgs.runCommand "asset-manifest" {
151 processAssets = { src, packageName ? "obelisk-generated-static", moduleName ? "Obelisk.Generated.Static" }: pkgs.runCommand "asset-manifest" {
148 inherit src;
152 inherit src;
149 outputs = [ "out" "haskellManifest" "symlinked" ];
153 outputs = [ "out" "haskellManifest" "symlinked" ];
150− buildInputs = [
154+ nativeBuildInputs = [ ghcObelisk.obelisk-asset-manifest ];
151− (reflex-platform.ghc.callCabal2nix "obelisk-asset-manifest" (hackGet ./lib/asset + "/manifest") {})
154 set -euo pipefail
156 set -euo pipefail
155 touch "$out"
157 touch "$out"
158+ mkdir -p "$symlinked"
156 obelisk-asset-manifest-generate "$src" "$haskellManifest" ${packageName} ${moduleName} "$symlinked"
159 obelisk-asset-manifest-generate "$src" "$haskellManifest" ${packageName} ${moduleName} "$symlinked"
159− compressedJs = frontend: pkgs.runCommand "compressedJs" { buildInputs = [ pkgs.closurecompiler ]; } ''
162+ compressedJs = frontend: optimizationLevel: pkgs.runCommand "compressedJs" { buildInputs = [ pkgs.closurecompiler ]; } ''
160 mkdir $out
163 mkdir $out
162− ln -s "${justStaticExecutables frontend}/bin/frontend.jsexe/all.js" all.unminified.js
165+ ln -s "${haskellLib.justStaticExecutables frontend}/bin/frontend.jsexe/all.js" all.unminified.js
163− closure-compiler --externs "${reflex-platform.ghcjsExternsJs}" -O ADVANCED --jscomp_warning=checkVars --create_source_map="all.js.map" --source_map_format=V3 --js_output_file="all.js" all.unminified.js
166+ closure-compiler --externs "${reflex-platform.ghcjsExternsJs}" -O ${optimizationLevel} --jscomp_warning=checkVars --create_source_map="all.js.map" --source_map_format=V3 --js_output_file="all.js" all.unminified.js
164 echo "//# sourceMappingURL=all.js.map" >> all.js
167 echo "//# sourceMappingURL=all.js.map" >> all.js
@@ -231,17 +234,18 @@ rec {
234− serverExe = backend: frontend: assets: config:
237+ serverExe = backend: frontend: assets: config: optimizationLevel: version:
235 pkgs.runCommand "serverExe" {} ''
238 pkgs.runCommand "serverExe" {} ''
236 mkdir $out
239 mkdir $out
238− ln -s "${justStaticExecutables backend}"/bin/* $out/
241+ ln -s "${haskellLib.justStaticExecutables backend}"/bin/* $out/
239 ln -s "${mkAssets assets}" $out/static.assets
242 ln -s "${mkAssets assets}" $out/static.assets
240 cp -r ${config} $out/config
243 cp -r ${config} $out/config
241− ln -s ${mkAssets (compressedJs frontend)} $out/frontend.jsexe.assets
244+ ln -s ${mkAssets (compressedJs frontend optimizationLevel)} $out/frontend.jsexe.assets
245+ echo ${version} > $out/version
244− server = { exe, hostName, adminEmail, routeHost, enableHttps, config }@args:
248+ server = { exe, hostName, adminEmail, routeHost, enableHttps, config, version }@args:
246 nixos = import (pkgs.path + /nixos);
250 nixos = import (pkgs.path + /nixos);
247 in nixos {
251 in nixos {
@@ -258,35 +262,35 @@ rec {
258 # An Obelisk project is a reflex-platform project with a predefined layout and role for each component
262 # An Obelisk project is a reflex-platform project with a predefined layout and role for each component
259 project = base: projectDefinition:
263 project = base: projectDefinition:
260 let configPath = base + "/config";
264 let configPath = base + "/config";
261− static = base + "/static";
262− processedStatic = processAssets { src = static; };
263 projectOut = sys: (getReflexPlatform sys).project (args@{ nixpkgs, ... }:
265 projectOut = sys: (getReflexPlatform sys).project (args@{ nixpkgs, ... }:
264 let mkProject = { android ? null #TODO: Better error when missing
266 let mkProject = { android ? null #TODO: Better error when missing
265 , ios ? null #TODO: Better error when missing
267 , ios ? null #TODO: Better error when missing
266 , packages ? {}
268 , packages ? {}
267 , overrides ? _: _: {}
269 , overrides ? _: _: {}
270+ , staticFiles ? base + /static
268 , tools ? _: []
271 , tools ? _: []
269 , shellToolOverrides ? _: _: {}
272 , shellToolOverrides ? _: _: {}
270 , withHoogle ? false # Setting this to `true` makes shell reloading far slower
273 , withHoogle ? false # Setting this to `true` makes shell reloading far slower
274+ , __closureCompilerOptimizationLevel ? "ADVANCED"
272 let frontendName = "frontend";
276 let frontendName = "frontend";
273 backendName = "backend";
277 backendName = "backend";
274 commonName = "common";
278 commonName = "common";
275 staticName = "obelisk-generated-static";
279 staticName = "obelisk-generated-static";
276− staticPath = base + "/static";
280+ staticFilesImpure = if lib.isDerivation staticFiles then staticFiles else toString staticFiles;
281+ processedStatic = processAssets { src = staticFiles; };
277 # The packages whose names and roles are defined by this package
282 # The packages whose names and roles are defined by this package
278− predefinedPackages = filterAttrs (_: x: x != null) {
283+ predefinedPackages = lib.filterAttrs (_: x: x != null) {
279 ${frontendName} = nullIfAbsent (base + "/frontend");
284 ${frontendName} = nullIfAbsent (base + "/frontend");
280 ${commonName} = nullIfAbsent (base + "/common");
285 ${commonName} = nullIfAbsent (base + "/common");
281 ${backendName} = nullIfAbsent (base + "/backend");
286 ${backendName} = nullIfAbsent (base + "/backend");
283 combinedPackages = predefinedPackages // packages;
288 combinedPackages = predefinedPackages // packages;
284 projectOverrides = self: super: {
289 projectOverrides = self: super: {
285− ${staticName} = dontHaddock (self.callCabal2nix "static" processedStatic.haskellManifest {});
290+ ${staticName} = haskellLib.dontHaddock (self.callCabal2nix staticName processedStatic.haskellManifest {});
286− ${backendName} = addBuildDepend super.${backendName} self.obelisk-run;
291+ ${backendName} = haskellLib.addBuildDepend super.${backendName} self.obelisk-run;
288− totalOverrides = composeExtensions (composeExtensions defaultHaskellOverrides projectOverrides) overrides;
293+ totalOverrides = lib.composeExtensions projectOverrides overrides;
289− inherit (nixpkgs) lib;
290 inherit (lib.strings) hasPrefix;
294 inherit (lib.strings) hasPrefix;
291 privateConfigDirs = ["config/backend"];
295 privateConfigDirs = ["config/backend"];
292 injectableConfig = builtins.filterSource (path: _:
296 injectableConfig = builtins.filterSource (path: _:
@@ -297,16 +301,16 @@ rec {
297 overrides = totalOverrides;
301 overrides = totalOverrides;
298 packages = combinedPackages;
302 packages = combinedPackages;
299 shells = {
303 shells = {
300− ghcSavedSplices = (filter (x: hasAttr x combinedPackages) [
304+ ${if android == null && ios == null then null else "ghcSavedSplices"} = (lib.filter (x: lib.hasAttr x combinedPackages) [
301 commonName
305 commonName
302 frontendName
306 frontendName
304− ghc = (filter (x: hasAttr x combinedPackages) [
308+ ghc = (lib.filter (x: lib.hasAttr x combinedPackages) [
305 backendName
309 backendName
306 commonName
310 commonName
307 frontendName
311 frontendName
309− ghcjs = filter (x: hasAttr x combinedPackages) [
313+ ghcjs = lib.filter (x: lib.hasAttr x combinedPackages) [
310 frontendName
314 frontendName
311 commonName
315 commonName
@@ -314,33 +318,39 @@ rec {
314 android = {
318 android = {
315 ${if android == null then null else frontendName} = {
319 ${if android == null then null else frontendName} = {
316 executableName = "frontend";
320 executableName = "frontend";
317− ${if builtins.pathExists staticPath then "assets" else null} =
321+ ${if builtins.pathExists staticFiles then "assets" else null} =
318− executableConfig.platforms.android.inject injectableConfig processedStatic.symlinked;
322+ nixpkgs.obeliskExecutableConfig.platforms.android.inject injectableConfig processedStatic.symlinked;
319 } // android;
323 } // android;
322 ${if ios == null then null else frontendName} = {
326 ${if ios == null then null else frontendName} = {
323 executableName = "frontend";
327 executableName = "frontend";
324− ${if builtins.pathExists staticPath then "staticSrc" else null} =
328+ ${if builtins.pathExists staticFiles then "staticSrc" else null} =
325− executableConfig.platforms.ios.inject injectableConfig processedStatic.symlinked;
329+ nixpkgs.obeliskExecutableConfig.platforms.ios.inject injectableConfig processedStatic.symlinked;
326 } // ios;
330 } // ios;
332+ passthru = { inherit android ios packages overrides tools shellToolOverrides withHoogle staticFiles staticFilesImpure __closureCompilerOptimizationLevel; };
329 in mkProject (projectDefinition args));
334 in mkProject (projectDefinition args));
335+ serverOn = sys: config: version: serverExe
336+ (projectOut sys).ghc.backend
330− serverOn = sys: config: serverExe (projectOut sys).ghc.backend (projectOut system).ghcjs.frontend static config;
337+ (projectOut system).ghcjs.frontend
338+ (projectOut sys).passthru.staticFiles
340+ (projectOut sys).passthru.__closureCompilerOptimizationLevel
331 linuxExe = serverOn "x86_64-linux";
342 linuxExe = serverOn "x86_64-linux";
343+ dummyVersion = "Version number is only available for deployments";
332 in projectOut system // {
344 in projectOut system // {
333 linuxExeConfigurable = linuxExe;
345 linuxExeConfigurable = linuxExe;
334− linuxExe = linuxExe (base + "/config");
346+ linuxExe = linuxExe (base + "/config") dummyVersion;
335− exe = serverOn system (base + "/config") ;
347+ exe = serverOn system (base + "/config") dummyVersion;
336− server = args@{ hostName, adminEmail, routeHost, enableHttps, config }: let
348+ server = args@{ hostName, adminEmail, routeHost, enableHttps, config, version }: let
337− injectableConfig = builtins.filterSource (path: _: !(hasPrefix (toString config + "/backend") (toString path))) config;
349+ injectableConfig = builtins.filterSource (path: _: !(lib.hasPrefix (toString config + "/backend") (toString path))) config;
338− in server (args // { exe = linuxExe injectableConfig; });
350+ in server (args // { exe = linuxExe injectableConfig version; });
339 obelisk = import (base + "/.obelisk/impl") {};
351 obelisk = import (base + "/.obelisk/impl") {};
341 haskellPackageSets = {
353 haskellPackageSets = {
342− ghc = reflex-platform.ghc.override {
354+ inherit (reflex-platform) ghc ghcjs;
343− overrides = defaultHaskellOverrides;
dep/reflex-platform/github.json+2−2
@@ -2,6 +2,6 @@
2 "owner": "reflex-frp",
2 "owner": "reflex-frp",
3 "repo": "reflex-platform",
3 "repo": "reflex-platform",
4 "branch": "develop",
4 "branch": "develop",
5− "rev": "2f09cea8aea453969172fe1f499905af5afb4719",
5+ "rev": "018576456043fe8372a0332c93245a4a620c1fb7",
6− "sha256": "1v7v2fwahq4mcywjvg1i44jyqimpxd4kgn4x4a24lcdgw9yll9wg"
6+ "sha256": "0qhnyyf96iajz97pbqfsw2l1kkbr1yq3bvw3qhjk031vdrkv7b7y"
lib/backend/obelisk-backend.cabal+1−1
@@ -17,7 +17,7 @@ library
17 obelisk-executable-config-inject,
17 obelisk-executable-config-inject,
18 obelisk-frontend,
18 obelisk-frontend,
19 obelisk-route,
19 obelisk-route,
20− obelisk-snap,
20+ obelisk-snap-extras,
21 reflex-dom,
21 reflex-dom,
23 snap-server,
23 snap-server,
lib/backend/src/Obelisk/Backend.hs+37−17
@@ -5,6 +5,7 @@
5{-# LANGUAGE LambdaCase #-}
5{-# LANGUAGE LambdaCase #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE OverloadedStrings #-}
8+{-# LANGUAGE ScopedTypeVariables #-}
8{-# LANGUAGE TemplateHaskell #-}
9{-# LANGUAGE TemplateHaskell #-}
9module Obelisk.Backend
10module Obelisk.Backend
10 ( Backend (..)
11 ( Backend (..)
@@ -16,6 +17,8 @@ module Obelisk.Backend
16 , serveDefaultObeliskApp
17 , serveDefaultObeliskApp
17 , prettifyOutput
18 , prettifyOutput
18 , runBackend
19 , runBackend
20+ , staticRenderContentType
21import Prelude hiding (id, (.))
24import Prelude hiding (id, (.))
@@ -29,6 +32,7 @@ import Data.Default (Default (..))
29import Data.Dependent.Sum
32import Data.Dependent.Sum
30import Data.Functor.Sum
33import Data.Functor.Sum
31import Data.Functor.Identity
34import Data.Functor.Identity
35+import Data.Monoid ((<>))
32import Data.Text (Text)
36import Data.Text (Text)
33import qualified Data.Text as T
37import qualified Data.Text as T
34import Data.Text.Encoding
38import Data.Text.Encoding
@@ -36,9 +40,10 @@ import Obelisk.Asset.Serve.Snap (serveAsset)
36import Obelisk.ExecutableConfig.Inject (injectExecutableConfigs)
40import Obelisk.ExecutableConfig.Inject (injectExecutableConfigs)
37import Obelisk.Frontend
41import Obelisk.Frontend
38import Obelisk.Route
42import Obelisk.Route
43+import Obelisk.Snap.Extras (doNotCache, serveFileIfExistsAs)
39import Reflex.Dom
44import Reflex.Dom
40−import Snap (MonadSnap, Snap, commandLineConfig, defaultConfig, getsRequest, httpServe, rqPathInfo,
45+import Snap (MonadSnap, Snap, commandLineConfig, defaultConfig, getsRequest, httpServe, modifyResponse
41− rqQueryString, writeBS, writeText)
46+ , rqPathInfo, rqQueryString, setContentType, writeBS, writeText)
42import Snap.Internal.Http.Server.Config (Config (accessLog, errorLog), ConfigLog (ConfigIoLog))
47import Snap.Internal.Http.Server.Config (Config (accessLog, errorLog), ConfigLog (ConfigIoLog))
43import System.IO (BufferMode (..), hSetBuffering, stderr, stdout)
48import System.IO (BufferMode (..), hSetBuffering, stderr, stdout)
@@ -55,8 +60,8 @@ data GhcjsApp route = GhcjsApp
56-- | Serve a frontend, which must be the same frontend that Obelisk has built and placed in the default location
61-- | Serve a frontend, which must be the same frontend that Obelisk has built and placed in the default location
57--TODO: The frontend should be provided together with the asset paths so that this isn't so easily breakable; that will probably make this function obsolete
62--TODO: The frontend should be provided together with the asset paths so that this isn't so easily breakable; that will probably make this function obsolete
58−serveDefaultObeliskApp :: MonadSnap m => Frontend (R appRoute) -> R (ObeliskRoute appRoute) -> m ()
63+serveDefaultObeliskApp :: MonadSnap m => (R appRoute -> Text) -> ([Text] -> m ()) -> Frontend (R appRoute) -> R (ObeliskRoute appRoute) -> m ()
59−serveDefaultObeliskApp frontend = serveObeliskApp defaultStaticAssets frontendApp
64+serveDefaultObeliskApp urlEnc serveStaticAsset frontend = serveObeliskApp urlEnc serveStaticAsset frontendApp
60 where frontendApp = GhcjsApp
65 where frontendApp = GhcjsApp
61 { _ghcjsApp_compiled = defaultFrontendGhcjsAssets
66 { _ghcjsApp_compiled = defaultFrontendGhcjsAssets
62 , _ghcjsApp_value = frontend
67 , _ghcjsApp_value = frontend
@@ -107,16 +112,17 @@ getRouteWith e = do
107 pageName <- getPageName
112 pageName <- getPageName
108 return $ tryDecode e pageName
113 return $ tryDecode e pageName
110−serveObeliskApp :: MonadSnap m => StaticAssets -> GhcjsApp (R appRoute) -> R (ObeliskRoute appRoute) -> m ()
115+serveObeliskApp :: MonadSnap m => (R appRoute -> Text) -> ([Text] -> m ()) -> GhcjsApp (R appRoute) -> R (ObeliskRoute appRoute) -> m ()
111−serveObeliskApp staticAssets frontendApp = \case
116+serveObeliskApp urlEnc serveStaticAsset frontendApp = \case
112− ObeliskRoute_App appRouteComponent :=> Identity appRouteRest -> serveGhcjsApp frontendApp $ GhcjsAppRoute_App appRouteComponent :/ appRouteRest
117+ ObeliskRoute_App appRouteComponent :=> Identity appRouteRest -> serveGhcjsApp urlEnc frontendApp $ GhcjsAppRoute_App appRouteComponent :/ appRouteRest
113 ObeliskRoute_Resource resComponent :=> Identity resRest -> case resComponent :=> Identity resRest of
118 ObeliskRoute_Resource resComponent :=> Identity resRest -> case resComponent :=> Identity resRest of
114− ResourceRoute_Static :=> Identity pathSegments -> serveStaticAssets staticAssets pathSegments
119+ ResourceRoute_Static :=> Identity pathSegments -> serveStaticAsset pathSegments
115− ResourceRoute_Ghcjs :=> Identity pathSegments -> serveGhcjsApp frontendApp $ GhcjsAppRoute_Resource :/ pathSegments
120+ ResourceRoute_Ghcjs :=> Identity pathSegments -> serveGhcjsApp urlEnc frontendApp $ GhcjsAppRoute_Resource :/ pathSegments
116 ResourceRoute_JSaddleWarp :=> Identity _ -> do
121 ResourceRoute_JSaddleWarp :=> Identity _ -> do
117 let msg = "Error: Obelisk.Backend received jsaddle request"
122 let msg = "Error: Obelisk.Backend received jsaddle request"
118 liftIO $ putStrLn $ T.unpack msg
123 liftIO $ putStrLn $ T.unpack msg
119 writeText msg
124 writeText msg
125+ ResourceRoute_Version :=> Identity () -> doNotCache >> serveFileIfExistsAs "text/plain" "version"
121serveStaticAssets :: MonadSnap m => StaticAssets -> [Text] -> m ()
127serveStaticAssets :: MonadSnap m => StaticAssets -> [Text] -> m ()
122serveStaticAssets assets pathSegments = serveAsset (_staticAssets_processed assets) (_staticAssets_unprocessed assets) $ T.unpack $ T.intercalate "/" pathSegments
128serveStaticAssets assets pathSegments = serveAsset (_staticAssets_processed assets) (_staticAssets_unprocessed assets) $ T.unpack $ T.intercalate "/" pathSegments
@@ -131,11 +137,15 @@ data GhcjsAppRoute :: (* -> *) -> * -> * where
131 GhcjsAppRoute_App :: appRouteComponent a -> GhcjsAppRoute appRouteComponent a
137 GhcjsAppRoute_App :: appRouteComponent a -> GhcjsAppRoute appRouteComponent a
132 GhcjsAppRoute_Resource :: GhcjsAppRoute appRouteComponent [Text]
138 GhcjsAppRoute_Resource :: GhcjsAppRoute appRouteComponent [Text]
140+staticRenderContentType :: ByteString
141+staticRenderContentType = "text/html; charset=utf-8"
134--TODO: Don't assume we're being served at "/"
143--TODO: Don't assume we're being served at "/"
135−serveGhcjsApp :: MonadSnap m => GhcjsApp (R appRouteComponent) -> R (GhcjsAppRoute appRouteComponent) -> m ()
144+serveGhcjsApp :: MonadSnap m => (R appRouteComponent -> Text) -> GhcjsApp (R appRouteComponent) -> R (GhcjsAppRoute appRouteComponent) -> m ()
136−serveGhcjsApp app = \case
145+serveGhcjsApp urlEnc app = \case
137− GhcjsAppRoute_App appRouteComponent :=> Identity appRouteRest ->
146+ GhcjsAppRoute_App appRouteComponent :=> Identity appRouteRest -> do
147+ modifyResponse $ setContentType staticRenderContentType
138− writeBS <=< liftIO $ renderGhcjsFrontend (appRouteComponent :/ appRouteRest) $ _ghcjsApp_value app
148+ writeBS <=< liftIO $ renderGhcjsFrontend urlEnc (appRouteComponent :/ appRouteRest) $ _ghcjsApp_value app
139 GhcjsAppRoute_Resource :=> Identity pathSegments -> serveStaticAssets (_ghcjsApp_compiled app) pathSegments
149 GhcjsAppRoute_Resource :=> Identity pathSegments -> serveStaticAssets (_ghcjsApp_compiled app) pathSegments
141runBackend :: Backend fullRoute frontendRoute -> Frontend (R frontendRoute) -> IO ()
151runBackend :: Backend fullRoute frontendRoute -> Frontend (R frontendRoute) -> IO ()
@@ -146,10 +156,20 @@ runBackend backend frontend = case checkEncoder $ _backend_routeEncoder backend
146 getRouteWith validFullEncoder >>= \case
156 getRouteWith validFullEncoder >>= \case
147 Identity r -> case r of
157 Identity r -> case r of
148 InL backendRoute :=> Identity a -> serveRoute $ backendRoute :/ a
158 InL backendRoute :=> Identity a -> serveRoute $ backendRoute :/ a
149− InR obeliskRoute :=> Identity a -> serveDefaultObeliskApp frontend $ obeliskRoute :/ a
159+ InR obeliskRoute :=> Identity a ->
160+ serveDefaultObeliskApp (mkRouteToUrl validFullEncoder) (serveStaticAssets defaultStaticAssets) frontend $ obeliskRoute :/ a
162+mkRouteToUrl :: Encoder Identity parse (R (Sum f (ObeliskRoute r))) PageName -> R r -> Text
163+mkRouteToUrl validFullEncoder =
164+ let pageNameEncoder' :: Encoder Identity (Either Text) PageName PathQuery = pageNameEncoder
165+ in \(k :/ v) -> T.pack . uncurry (<>) . encode pageNameEncoder' . encode validFullEncoder $ (InR $ ObeliskRoute_App k) :/ v
151−renderGhcjsFrontend :: route -> Frontend route -> IO ByteString
168+renderGhcjsFrontend :: MonadIO m => (route -> Text) -> route -> Frontend route -> m ByteString
152−renderGhcjsFrontend route f = do
169+renderGhcjsFrontend urlEnc route f = do
153 let baseTag = elAttr "base" ("href" =: "/") blank --TODO: Figure out the base URL from the routes
170 let baseTag = elAttr "base" ("href" =: "/") blank --TODO: Figure out the base URL from the routes
171+ ghcjsPreload = elAttr "link" ("rel" =: "preload" <> "as" =: "script" <> "href" =: "ghcjs/all.js") blank
154 ghcjsScript = elAttr "script" ("language" =: "javascript" <> "src" =: "ghcjs/all.js" <> "defer" =: "defer") blank
172 ghcjsScript = elAttr "script" ("language" =: "javascript" <> "src" =: "ghcjs/all.js" <> "defer" =: "defer") blank
173+ liftIO $ renderFrontendHtml urlEnc route
155− renderFrontendHtml route (_frontend_head f >> injectExecutableConfigs >> baseTag) (_frontend_body f >> ghcjsScript)
174+ (_frontend_head f >> injectExecutableConfigs >> baseTag >> ghcjsPreload)
175+ (_frontend_body f >> ghcjsScript)
lib/cliapp/src/Obelisk/CliApp.hs+2
@@ -37,10 +37,12 @@ module Obelisk.CliApp
37 , AsProcessFailure (..)
37 , AsProcessFailure (..)
38 , readProcessAndLogStderr
38 , readProcessAndLogStderr
39 , readProcessAndLogOutput
39 , readProcessAndLogOutput
40+ , readCreateProcessWithExitCode
40 , callProcessAndLogOutput
41 , callProcessAndLogOutput
41 , createProcess_
42 , createProcess_
42 , callProcess
43 , callProcess
43 , callCommand
44 , callCommand
46import Control.Monad.Log (Severity (..))
48import Control.Monad.Log (Severity (..))
lib/cliapp/src/Obelisk/CliApp/Process.hs+10−1
@@ -13,11 +13,13 @@ module Obelisk.CliApp.Process
13 , AsProcessFailure (..)
13 , AsProcessFailure (..)
14 , readProcessAndLogStderr
14 , readProcessAndLogStderr
15 , readProcessAndLogOutput
15 , readProcessAndLogOutput
16+ , readCreateProcessWithExitCode
16 , callProcessAndLogOutput
17 , callProcessAndLogOutput
17 , createProcess
18 , createProcess
18 , createProcess_
19 , createProcess_
19 , callProcess
20 , callProcess
20 , callCommand
21 , callCommand
23import Control.Monad ((<=<), join, void)
25import Control.Monad ((<=<), join, void)
@@ -31,7 +33,6 @@ import Data.Monoid ((<>))
31import Data.Text (Text)
33import Data.Text (Text)
32import qualified Data.Text as T
34import qualified Data.Text as T
33import qualified Data.Text.Encoding as T
35import qualified Data.Text.Encoding as T
34−--import qualified Data.Text.IO as T
35import System.Exit (ExitCode (..))
36import System.Exit (ExitCode (..))
36import System.IO (Handle)
37import System.IO (Handle)
37import System.IO.Streams (InputStream, handleToInputStream)
38import System.IO.Streams (InputStream, handleToInputStream)
@@ -65,6 +66,13 @@ readProcessAndLogStderr sev process = do
65 streamToLog =<< liftIO (streamHandle sev err)
66 streamToLog =<< liftIO (streamHandle sev err)
66 liftIO $ T.decodeUtf8 <$> BS.hGetContents out
67 liftIO $ T.decodeUtf8 <$> BS.hGetContents out
69+readCreateProcessWithExitCode
70+ :: (MonadIO m, CliLog m, CliThrow e m, AsProcessFailure e)
71+ => CreateProcess -> m (ExitCode, String, String)
72+readCreateProcessWithExitCode process = do
73+ putLog Debug $ "Creating process: " <> reconstructCommand (cmdspec process)
74+ liftIO $ Process.readCreateProcessWithExitCode process ""
68-- | Like `System.Process.readProcess` but logs the combined output (stdout and stderr)
76-- | Like `System.Process.readProcess` but logs the combined output (stdout and stderr)
69-- with the corresponding severity.
77-- with the corresponding severity.
@@ -167,6 +175,7 @@ streamToLog stream = fix $ \loop -> do
167 Nothing -> return ()
175 Nothing -> return ()
168 Just (sev, line) -> putLogRaw sev (T.decodeUtf8 line) >> loop
176 Just (sev, line) -> putLogRaw sev (T.decodeUtf8 line) >> loop
178+-- | Pretty print a 'CmdSpec'
170reconstructCommand :: Process.CmdSpec -> Text
179reconstructCommand :: Process.CmdSpec -> Text
171reconstructCommand (Process.ShellCommand str) = T.pack str
180reconstructCommand (Process.ShellCommand str) = T.pack str
172reconstructCommand (Process.RawCommand c as) = processToShellString c as
181reconstructCommand (Process.RawCommand c as) = processToShellString c as
lib/command/obelisk-command.cabal+1−3
@@ -15,7 +15,6 @@ library
16 , bytestring
16 , bytestring
17 , obelisk-cliapp
17 , obelisk-cliapp
19 , containers
18 , containers
20 , data-default
19 , data-default
21 , directory
20 , directory
@@ -32,6 +31,7 @@ library
32 , modern-uri
31 , modern-uri
33 , monad-loops
32 , monad-loops
36 , network-uri
36 , network-uri
37 , optparse-applicative
37 , optparse-applicative
@@ -52,8 +52,6 @@ library
52 Obelisk.Command.Project
52 Obelisk.Command.Project
53 Obelisk.Command.Run
53 Obelisk.Command.Run
54 Obelisk.Command.Thunk
54 Obelisk.Command.Thunk
55− Obelisk.Command.Upgrade
56− Obelisk.Command.Upgrade.Hash
57 Obelisk.Command.Utils
55 Obelisk.Command.Utils
58 Obelisk.Command.VmBuilder
56 Obelisk.Command.VmBuilder
59 -- -fobject-code is so that the StaticPointers extension can work in ghci
57 -- -fobject-code is so that the StaticPointers extension can work in ghci
lib/command/src/Obelisk/Command.hs+30−118
@@ -14,8 +14,7 @@ import Data.Bool (bool)
14import qualified Data.ByteString.Base16 as Base16
14import qualified Data.ByteString.Base16 as Base16
15import qualified Data.ByteString.Lazy as LBS
15import qualified Data.ByteString.Lazy as LBS
16import Data.List
16import Data.List
17−import Data.Maybe (catMaybes, listToMaybe)
17+import Data.Maybe (catMaybes)
18−import Data.Text (Text)
19import qualified Data.Text as T
18import qualified Data.Text as T
20import Data.Text.Encoding
19import Data.Text.Encoding
21import GHC.StaticPtr
20import GHC.StaticPtr
@@ -34,11 +33,8 @@ import Obelisk.Command.Deploy
34import Obelisk.Command.Project
33import Obelisk.Command.Project
35import Obelisk.Command.Run
34import Obelisk.Command.Run
36import Obelisk.Command.Thunk
35import Obelisk.Command.Thunk
37−import Obelisk.Command.Upgrade
38−import Obelisk.Command.Upgrade.Hash (getDirectoryHash, getHashAtGitRevision)
39import Obelisk.Command.Utils
36import Obelisk.Command.Utils
40import qualified Obelisk.Command.VmBuilder as VmBuilder
37import qualified Obelisk.Command.VmBuilder as VmBuilder
41−import Obelisk.Migration (Hash)
44data Args = Args
40data Args = Args
@@ -95,16 +91,11 @@ data ObCommand
95 | ObCommand_Thunk ThunkCommand
91 | ObCommand_Thunk ThunkCommand
96 | ObCommand_Repl
92 | ObCommand_Repl
97 | ObCommand_Watch
93 | ObCommand_Watch
98− | ObCommand_Upgrade (Maybe Text)
99 | ObCommand_Internal ObInternal
94 | ObCommand_Internal ObInternal
100 deriving Show
95 deriving Show
102data ObInternal
97data ObInternal
103 = ObInternal_RunStaticIO StaticKey
98 = ObInternal_RunStaticIO StaticKey
104− | ObInternal_Hash (Maybe Text)
105− | ObInternal_CreateMigration
106− | ObInternal_VerifyMigration
107− | ObInternal_Migrate Hash
108 | ObInternal_CLIDemo
99 | ObInternal_CLIDemo
109 deriving Show
100 deriving Show
@@ -135,7 +126,6 @@ obCommand cfg = hsubparser
135 , command "thunk" $ info (ObCommand_Thunk <$> thunkCommand) $ progDesc "Manipulate thunk directories"
126 , command "thunk" $ info (ObCommand_Thunk <$> thunkCommand) $ progDesc "Manipulate thunk directories"
136 , command "repl" $ info (pure ObCommand_Repl) $ progDesc "Open an interactive interpreter"
127 , command "repl" $ info (pure ObCommand_Repl) $ progDesc "Open an interactive interpreter"
137 , command "watch" $ info (pure ObCommand_Watch) $ progDesc "Watch current project for errors and warnings"
128 , command "watch" $ info (pure ObCommand_Watch) $ progDesc "Watch current project for errors and warnings"
138− , command "upgrade" $ info (ObCommand_Upgrade <$> argument (maybeReader $ Just . Just . T.pack) (action "branch" <> metavar "GITBRANCH" <> value Nothing <> help "Git branch of obelisk to update to (defaults to the thunk's branch)")) $ progDesc "Upgrade Obelisk in the project"
140 <|> subparser
130 <|> subparser
@@ -181,7 +171,6 @@ deployInitOpts = DeployInitOpts
181 <*> strOption (long "route" <> metavar "PUBLICROUTE" <> help "Publicly accessible URL of your app")
171 <*> strOption (long "route" <> metavar "PUBLICROUTE" <> help "Publicly accessible URL of your app")
182 <*> strOption (long "admin-email" <> metavar "ADMINEMAIL" <> help "Email address where administrative alerts will be sent")
172 <*> strOption (long "admin-email" <> metavar "ADMINEMAIL" <> help "Email address where administrative alerts will be sent")
183 <*> flag True False (long "disable-https" <> help "Disable automatic https configuration for the backend")
173 <*> flag True False (long "disable-https" <> help "Disable automatic https configuration for the backend")
184− <*> strOption (long "upstream" <> value "origin" <> metavar "REMOTE" <> help "git remote to use for the src thunk" <> showDefault)
186type TeamID = String
175type TeamID = String
187data PlatformDeployment = Android | IOS TeamID
176data PlatformDeployment = Android | IOS TeamID
@@ -204,17 +193,12 @@ data DeployInitOpts = DeployInitOpts
204 , _deployInitOpts_route :: String
193 , _deployInitOpts_route :: String
205 , _deployInitOpts_adminEmail :: String
194 , _deployInitOpts_adminEmail :: String
206 , _deployInitOpts_enableHttps :: Bool
195 , _deployInitOpts_enableHttps :: Bool
207− , _deployInitOpts_remote :: String
209 deriving Show
197 deriving Show
211internalCommand :: Parser ObInternal
199internalCommand :: Parser ObInternal
212internalCommand = subparser $ mconcat
200internalCommand = subparser $ mconcat
213 [ command "run-static-io" $ info (ObInternal_RunStaticIO <$> argument (eitherReader decodeStaticKey) (action "static-key")) mempty
201 [ command "run-static-io" $ info (ObInternal_RunStaticIO <$> argument (eitherReader decodeStaticKey) (action "static-key")) mempty
214− , command "hash" $ info (ObInternal_Hash <$> argument (maybeReader $ Just . Just . T.pack) (action "rev" <> metavar "GITREVISION" <> value Nothing <> help "Calculate for the specified git revision (defaults to working copy")) $ progDesc "Computes hash of working directory (or git revision)"
215− , command "create-migration" $ info (pure ObInternal_CreateMigration) mempty
216− , command "verify-migration" $ info (pure ObInternal_VerifyMigration) mempty
217− , command "migrate" $ info (ObInternal_Migrate <$> strArgument (action "fromHash" <> metavar "FROMHASH" <> help "Migrate from this hash")) $ progDesc "Perform a migrate from the given hash to HEAD of obelisk thunk"
218 , command "clidemo" $ info (pure ObInternal_CLIDemo) mempty
202 , command "clidemo" $ info (pure ObInternal_CLIDemo) mempty
@@ -226,32 +210,17 @@ thunkDirectoryParser = fmap (dropTrailingPathSeparator . normalise) . strArgumen
226 , help "Path to directory containing thunk data"
210 , help "Path to directory containing thunk data"
229−data ThunkPackOpts = ThunkPackOpts
230− { _thunkPackOpts_directory :: FilePath
231− , _thunkPackOpts_upstream :: String
235data ThunkCommand
213data ThunkCommand
236 = ThunkCommand_Update [FilePath]
214 = ThunkCommand_Update [FilePath]
237 | ThunkCommand_Unpack [FilePath]
215 | ThunkCommand_Unpack [FilePath]
238− | ThunkCommand_Pack [ThunkPackOpts]
216+ | ThunkCommand_Pack [FilePath]
239 deriving Show
217 deriving Show
241−thunkPackOpts :: Parser ThunkPackOpts
242−thunkPackOpts = (ThunkPackOpts <$> thunkDirectoryParser <*>) . strOption $ mconcat
246− , help "Git remote that packed thunk will point to"
250thunkCommand :: Parser ThunkCommand
219thunkCommand :: Parser ThunkCommand
251thunkCommand = hsubparser $ mconcat
220thunkCommand = hsubparser $ mconcat
252 [ command "update" $ info (ThunkCommand_Update <$> some thunkDirectoryParser) $ progDesc "Update thunk to latest revision available"
221 [ command "update" $ info (ThunkCommand_Update <$> some thunkDirectoryParser) $ progDesc "Update thunk to latest revision available"
253 , command "unpack" $ info (ThunkCommand_Unpack <$> some thunkDirectoryParser) $ progDesc "Unpack thunk into git checkout of revision it points to"
222 , command "unpack" $ info (ThunkCommand_Unpack <$> some thunkDirectoryParser) $ progDesc "Unpack thunk into git checkout of revision it points to"
254− , command "pack" $ info (ThunkCommand_Pack <$> some thunkPackOpts) $ progDesc "Pack git checkout into thunk that points at given upstream"
223+ , command "pack" $ info (ThunkCommand_Pack <$> some thunkDirectoryParser) $ progDesc "Pack git checkout into thunk that points at the current branch's upstream"
257parserPrefs :: ParserPrefs
226parserPrefs :: ParserPrefs
@@ -269,18 +238,10 @@ mkObeliskConfig = do
269 -- This function should not use argument parser (full argument parsing happens post handoff)
238 -- This function should not use argument parser (full argument parsing happens post handoff)
270 let logLevel = toLogLevel $ "-v" `elem` cliArgs
239 let logLevel = toLogLevel $ "-v" `elem` cliArgs
271 notInteractive <- not <$> isInteractiveTerm
240 notInteractive <- not <$> isInteractiveTerm
272−-- instance MonadIO m => MonadError (Either Text ProcessFailed) (DieT m) where
273−-- throwError = \case
276−-- liftIO $ exitWith $ ExitFailure 2
277−-- Right (ProcessFailed p code) -> do
278−-- putLog Alert $ "Process exited with code " <> T.pack (show code) <> "; " <> T.pack (show p)
279−-- liftIO $ exitWith $ ExitFailure 2
280 cliConf <- newCliConfig logLevel notInteractive notInteractive $ \case
241 cliConf <- newCliConfig logLevel notInteractive notInteractive $ \case
281 ObeliskError_ProcessError (ProcessFailure p code) ann ->
242 ObeliskError_ProcessError (ProcessFailure p code) ann ->
282− ( "Process exited with code " <> T.pack (show code) <> "; " <> T.pack (show p)
243+ ( "Process exited with code " <> T.pack (show code) <> "; " <> reconstructCommand p
283− <> maybe "" ("\n\n" <>) ann
244+ <> maybe "" ("\n" <>) ann
286 ObeliskError_Unstructured msg -> (msg, 2)
247 ObeliskError_Unstructured msg -> (msg, 2)
@@ -322,65 +283,29 @@ main' argsCfg = do
322 , "logging-level=" <> show logLevel
283 , "logging-level=" <> show logLevel
325− (mainWithHandOff argsCfg <=< parseHandoff) =<< liftIO getArgs
286+ --TODO: We'd like to actually use the parser to determine whether to hand off,
326−
287+ --but in the case where this implementation of 'ob' doesn't support all
327−-- Type representing the result of a handoff calculation.
288+ --arguments being passed along, this could fail. For now, we don't bother
328−data HandOff m
289+ --with optparse-applicative until we've done the handoff.
329− = HandOff_Yes FilePath [String] -- Handoff immediately to the given impl with the given args
290+ let go as = do
330− | HandOff_Decide (m Bool) FilePath [String] -- Handoff only if the action returns True
291+ args' <- liftIO $ handleParseResult (execParserPure parserPrefs (argsInfo argsCfg) as)
331− | HandOff_No [String] -- Do not handoff, and continue with the given args
333−mainWithHandOff :: MonadObelisk m => ArgsConfig -> HandOff m -> m ()
334−mainWithHandOff argsCfg = \case
335− HandOff_Yes impl as -> do
336− putLog Debug $ "Handing off to project obelisk " <> T.pack impl
337− liftIO $ executeFile impl False ("--no-handoff" : as) Nothing
338− HandOff_Decide f impl as -> do
339− withSpinner' "Deciding whether to handoff"
341− "Continuing in ambient obelisk without handing off"
342− "Handed off to project obelisk") f >>= \case
343− True -> mainWithHandOff argsCfg $ HandOff_Yes impl as
344− False -> mainWithHandOff argsCfg $ HandOff_No as
346− putLog Debug $ "Not handing off"
347− args' <- liftIO $ parseCLIArgs argsCfg as
348− warnIfExtraneousFlag args'
349− ob $ _args_command args'
351− warnIfExtraneousFlag a = case _args_noHandOffPassed a of
292+ case _args_noHandOffPassed args' of
352− False -> return ()
293+ False -> return ()
353− True -> putLog Warning $
354− "Ignoring unexpected --no-handoff (should only be passed once and as the first argument)"
294+ True -> putLog Warning "--no-handoff should only be passed once and as the first argument; ignoring"
355−
295+ ob $ _args_command args'
357−parseHandoff :: MonadObelisk m => [String] -> m (HandOff m)
358−parseHandoff as' = case hasNoHandoff as' of
360− pure $ HandOff_No as
361− (False, as) -> findProjectObeliskCommand "." >>= \case
296+ handoffAndGo as = findProjectObeliskCommand "." >>= \case
362− Nothing -> do
297+ Nothing -> go as -- If not in a project, just run ourselves
363− putLog Debug "Not in a project; no need to hand off"
364− pure $ HandOff_No as
365− Just impl -> case getSubCommand as of
298+ Just impl -> do
366− Just "upgrade" ->
299+ -- Invoke the real implementation, using --no-handoff to prevent infinite recursion
367− pure $ HandOff_Decide (decideHandOffToProjectOb ".") impl as
300+ putLog Debug $ "Handing off to " <> T.pack impl
368− _ ->
301+ liftIO $ executeFile impl False ("--no-handoff" : myArgs) Nothing
369− pure $ HandOff_Yes impl as
302+ case myArgs of
371− getSubCommand = listToMaybe . filter (not . isPrefixOf "-")
372− hasNoHandoff = \case
373− "--no-handoff" : xs ->
374− -- If we've been told not to hand off, don't hand off
303+ "--no-handoff" : as -> go as -- If we've been told not to hand off, don't hand off
377− -- Otherwise bash completion would always hand-off even if the user isn't trying to
304+ a:as -- Otherwise bash completion would always hand-off even if the user isn't trying to
378− | "--bash-completion" `isPrefixOf` x && "--no-handoff" `elem` xs ->
305+ | "--bash-completion" `isPrefixOf` a
379− (True, x:xs)
306+ && "--no-handoff" `elem` as -> go (a:as)
380− | otherwise ->
307+ | otherwise -> handoffAndGo (a:as)
381− (False, x:xs)
308+ as -> handoffAndGo as
385ob :: MonadObelisk m => ObCommand -> m ()
310ob :: MonadObelisk m => ObCommand -> m ()
386ob = \case
311ob = \case
@@ -402,7 +327,7 @@ ob = \case
402 Right (ThunkData_Packed ptr) -> return ptr
327 Right (ThunkData_Packed ptr) -> return ptr
403 Right (ThunkData_Checkout (Just ptr)) -> return ptr
328 Right (ThunkData_Checkout (Just ptr)) -> return ptr
404 Right (ThunkData_Checkout Nothing) ->
329 Right (ThunkData_Checkout Nothing) ->
405− getThunkPtr' False root (T.pack $ _deployInitOpts_remote deployOpts)
330+ getThunkPtr' False root
406 let sshKeyPath = _deployInitOpts_sshKey deployOpts
331 let sshKeyPath = _deployInitOpts_sshKey deployOpts
407 hostname = _deployInitOpts_hostname deployOpts
332 hostname = _deployInitOpts_hostname deployOpts
408 route = _deployInitOpts_route deployOpts
333 route = _deployInitOpts_route deployOpts
@@ -423,28 +348,15 @@ ob = \case
423 ObCommand_Thunk tc -> case tc of
348 ObCommand_Thunk tc -> case tc of
424 ThunkCommand_Update thunks -> mapM_ updateThunkToLatest thunks
349 ThunkCommand_Update thunks -> mapM_ updateThunkToLatest thunks
425 ThunkCommand_Unpack thunks -> mapM_ unpackThunk thunks
350 ThunkCommand_Unpack thunks -> mapM_ unpackThunk thunks
426− ThunkCommand_Pack thunks -> forM_ thunks $ \(ThunkPackOpts dir upstream) -> packThunk dir (T.pack upstream)
351+ ThunkCommand_Pack thunks -> forM_ thunks packThunk
427 ObCommand_Repl -> runRepl
352 ObCommand_Repl -> runRepl
428 ObCommand_Watch -> inNixShell' $ static runWatch
353 ObCommand_Watch -> inNixShell' $ static runWatch
429− ObCommand_Upgrade branch -> do
430− upgradeObelisk "." branch
431 ObCommand_Internal icmd -> case icmd of
354 ObCommand_Internal icmd -> case icmd of
432 ObInternal_RunStaticIO k -> liftIO (unsafeLookupStaticPtr @(ObeliskT IO ()) k) >>= \case
355 ObInternal_RunStaticIO k -> liftIO (unsafeLookupStaticPtr @(ObeliskT IO ()) k) >>= \case
433 Nothing -> failWith $ "ObInternal_RunStaticIO: no such StaticKey: " <> T.pack (show k)
356 Nothing -> failWith $ "ObInternal_RunStaticIO: no such StaticKey: " <> T.pack (show k)
434 Just p -> do
357 Just p -> do
435 c <- getObelisk
358 c <- getObelisk
436 liftIO $ runObelisk c $ deRefStaticPtr p
359 liftIO $ runObelisk c $ deRefStaticPtr p
437− ObInternal_Hash revM -> do
438− hash <- case revM of
439− Nothing -> getDirectoryHash [migrationDirName] "."
440− Just rev -> fmap head $ getHashAtGitRevision [rev] [migrationDirName] "."
442− ObInternal_CreateMigration ->
443− createMigrationEdgeFromHEAD "."
444− ObInternal_VerifyMigration ->
446− ObInternal_Migrate fromHash ->
447− migrateObelisk "." fromHash
448 ObInternal_CLIDemo -> cliDemo
360 ObInternal_CLIDemo -> cliDemo
450--TODO: Clean up all the magic strings throughout this codebase
362--TODO: Clean up all the magic strings throughout this codebase
lib/command/src/Obelisk/Command/Deploy.hs+24−29
@@ -88,37 +88,31 @@ deployPush deployPath getNixBuilders = do
88 route <- readDeployConfig deployPath $ "config" </> "common" </> "route"
88 route <- readDeployConfig deployPath $ "config" </> "common" </> "route"
89 routeHost <- getHostFromRoute enableHttps route
89 routeHost <- getHostFromRoute enableHttps route
90 let srcPath = deployPath </> "src"
90 let srcPath = deployPath </> "src"
92− builders <- getNixBuilders
93− buildOutput <- nixBuild $ def
94− { _nixBuildConfig_target = Target
95− { _target_path = srcPath
96− , _target_attr = Just "server.system"
98− , _nixBuildConfig_outLink = OutLink_None
99− , _nixBuildConfig_args =
100− [ strArg "hostName" host
101− , strArg "adminEmail" adminEmail
102− , strArg "routeHost" routeHost
103− , boolArg "enableHttps" enableHttps
104− , rawArg "config" $ deployPath </> "config"
106− , _nixBuildConfig_builders = builders
108− return $ listToMaybe $ lines buildOutput
109− result <- readThunk srcPath >>= \case
91+ thunkPtr <- readThunk srcPath >>= \case
110− Right (ThunkData_Packed _) ->
92+ Right (ThunkData_Packed ptr) -> return ptr
112 Right (ThunkData_Checkout _) -> do
93 Right (ThunkData_Checkout _) -> do
113 checkGitCleanStatus srcPath True >>= \case
94 checkGitCleanStatus srcPath True >>= \case
116− packThunk srcPath "origin" -- get upstream
95+ True -> packThunk srcPath
119− _ <- failWith $ T.pack $ "ob deploy push: ensure " <> srcPath <> " has no pending changes and latest is pushed upstream."
96+ False -> failWith $ T.pack $ "ob deploy push: ensure " <> srcPath <> " has no pending changes and latest is pushed upstream."
120− return Nothing
97+ Left err -> failWith $ "ob deploy push: couldn't read src thunk: " <> T.pack (show err)
121− _ -> return Nothing
98+ let version = show . _thunkRev_commit $ _thunkPtr_rev thunkPtr
99+ builders <- getNixBuilders
100+ buildOutput <- nixCmd $ NixCmd_Build $ def
101+ & nixCmdConfig_target .~Target
102+ { _target_path = srcPath
103+ , _target_attr = Just "server.system"
105+ & nixBuildConfig_outLink .~ OutLink_None
106+ & nixCmdConfig_args .~
107+ [ strArg "hostName" host
108+ , strArg "adminEmail" adminEmail
109+ , strArg "routeHost" routeHost
110+ , strArg "version" version
111+ , boolArg "enableHttps" enableHttps
112+ , rawArg "config" $ deployPath </> "config"
114+ & nixCmdConfig_builders .~ builders
115+ let result = listToMaybe $ lines buildOutput
122 forM_ result $ \res -> do
116 forM_ result $ \res -> do
123 let knownHostsPath = deployPath </> "backend_known_hosts"
117 let knownHostsPath = deployPath </> "backend_known_hosts"
124 sshOpts = sshArgs knownHostsPath (deployPath </> "ssh_key") False
118 sshOpts = sshArgs knownHostsPath (deployPath </> "ssh_key") False
@@ -177,6 +171,7 @@ verifyHostKey knownHostsPath keyPath hostName =
177 callProcessAndLogOutput (Notice, Warning) $ proc "ssh" $
171 callProcessAndLogOutput (Notice, Warning) $ proc "ssh" $
178 sshArgs knownHostsPath keyPath True <>
172 sshArgs knownHostsPath keyPath True <>
179 [ "root@" <> hostName
173 [ "root@" <> hostName
174+ , "-o", "NumberOfPasswordPrompts=0"
lib/command/src/Obelisk/Command/Nix.hs+103−64
@@ -6,11 +6,19 @@
6{-# LANGUAGE OverloadedStrings #-}
6{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE Rank2Types #-}
7{-# LANGUAGE Rank2Types #-}
8{-# LANGUAGE ScopedTypeVariables #-}
8{-# LANGUAGE ScopedTypeVariables #-}
9+{-# LANGUAGE TemplateHaskell #-}
9{-# LANGUAGE TypeApplications #-}
10{-# LANGUAGE TypeApplications #-}
10module Obelisk.Command.Nix
11module Obelisk.Command.Nix
11− ( nixBuild
12+ ( nixCmd
12− , withNixRemoteCheck
13+ , NixCmd (..)
14+ , nixCmdConfig_target
16+ , nixCmdConfig_builders
13 , NixBuildConfig (..)
17 , NixBuildConfig (..)
18+ , nixBuildConfig_outLink
19+ , NixInstantiateConfig (..)
20+ , nixInstantiateConfig_eval
21+ , NixCommonConfig (..)
14 , Target (..)
22 , Target (..)
15 , OutLink (..)
23 , OutLink (..)
16 , Arg (..)
24 , Arg (..)
@@ -19,36 +27,25 @@ module Obelisk.Command.Nix
22−--import Control.Monad.Catch (catch, throwM)
30+import Control.Monad (guard)
23import Control.Lens
31import Control.Lens
24−import Control.Monad.Except (ExceptT, runExceptT, throwError)
32+
25−import Control.Monad.IO.Class (liftIO)
26import Data.Bool (bool)
33import Data.Bool (bool)
27import Data.Default
34import Data.Default
28import Data.List (intercalate)
35import Data.List (intercalate)
29import Data.Monoid ((<>))
36import Data.Monoid ((<>))
30import qualified Data.Text as T
37import qualified Data.Text as T
31−import System.Directory
32−import System.Environment
33import System.Process (proc)
38import System.Process (proc)
35−import Obelisk.App (MonadInfallibleObelisk, MonadObelisk, ObeliskError (..))
40+import Obelisk.App (MonadObelisk)
36import Obelisk.CliApp
41import Obelisk.CliApp
38−-- | Where to put nix-build output
42− | OutLink_IndirectRoot FilePath
44−instance Default OutLink where
45− def = OutLink_Default
47-- | What to build
43-- | What to build
48data Target = Target
44data Target = Target
49 { _target_path :: FilePath
45 { _target_path :: FilePath
50 , _target_attr :: Maybe String
46 , _target_attr :: Maybe String
53instance Default Target where
50instance Default Target where
54 def = Target
51 def = Target
@@ -75,61 +72,103 @@ cliFromArgs = concatMap $ \case
75 Arg_Str k v -> ["--argstr", k, v]
72 Arg_Str k v -> ["--argstr", k, v]
76 Arg_Expr k v -> ["--arg", k, v]
73 Arg_Expr k v -> ["--arg", k, v]
78−data NixBuildConfig = NixBuildConfig
75+data NixCommonConfig = NixCommonConfig
79− { _nixBuildConfig_target :: Target
76+ { _nixCmdConfig_target :: Target
80− , _nixBuildConfig_outLink :: OutLink
77+ , _nixCmdConfig_args :: [Arg]
81− , _nixBuildConfig_args :: [Arg]
78+ , _nixCmdConfig_builders :: [String]
82− , _nixBuildConfig_builders :: [String]
80+makeClassy ''NixCommonConfig
85−instance Default NixBuildConfig where
82+instance Default NixCommonConfig where
86− def = NixBuildConfig def def mempty mempty
83+ def = NixCommonConfig def mempty mempty
88−nixBuild :: MonadObelisk m => NixBuildConfig -> m FilePath
85+runNixCommonConfig :: NixCommonConfig -> [FilePath]
89−nixBuild cfg = withSpinner' ("Running nix-build on " <> desc) (Just $ const $ "Built " <> desc) $ do
90− withNixRemoteCheck $ fmap T.unpack $ readProcessAndLogStderr Debug $ proc "nix-build" $ mconcat
91− [[path], attrArg, args, outLink, buildersArg]
86+runNixCommonConfig cfg = mconcat [[path], attrArg, args, buildersArg]
93− path = _target_path $ _nixBuildConfig_target cfg
88+ path = _target_path $ _nixCmdConfig_target cfg
94− attr = _target_attr $ _nixBuildConfig_target cfg
89+ attr = _target_attr $ _nixCmdConfig_target cfg
95 attrArg = case attr of
90 attrArg = case attr of
96 Nothing -> []
91 Nothing -> []
97 Just a -> ["-A", a]
92 Just a -> ["-A", a]
98− args = cliFromArgs $ _nixBuildConfig_args cfg
93+ args = cliFromArgs $ _nixCmdConfig_args cfg
94+ buildersArg = case _nixCmdConfig_builders cfg of
96+ builders -> ["--builders", intercalate ";" builders]
98+-- | Where to put nix-build output
102+ | OutLink_IndirectRoot FilePath
104+instance Default OutLink where
105+ def = OutLink_Default
107+data NixBuildConfig = NixBuildConfig
108+ { _nixBuildConfig_common :: NixCommonConfig
109+ , _nixBuildConfig_outLink :: OutLink
111+makeLenses ''NixBuildConfig
113+instance HasNixCommonConfig NixBuildConfig where
114+ nixCommonConfig = nixBuildConfig_common
116+instance Default NixBuildConfig where
117+ def = NixBuildConfig def def
119+runNixBuildConfig :: NixBuildConfig -> [FilePath]
120+runNixBuildConfig cfg = mconcat
121+ [ runNixCommonConfig $ cfg ^. nixCommonConfig
99− outLink = case _nixBuildConfig_outLink cfg of
122+ , case _nixBuildConfig_outLink cfg of
100 OutLink_Default -> []
123 OutLink_Default -> []
101 OutLink_None -> ["--no-out-link"]
124 OutLink_None -> ["--no-out-link"]
102 OutLink_IndirectRoot l -> ["--out-link", l]
125 OutLink_IndirectRoot l -> ["--out-link", l]
103− desc = T.pack $ path <> maybe "" (\a -> " [" <> a <> "]") attr
126+ ]
104− buildersArg = case _nixBuildConfig_builders cfg of
127+
105− [] -> []
128+data NixInstantiateConfig = NixInstantiateConfig
106− builders -> ["--builders", intercalate ";" builders]
129+ { _nixInstantiateConfig_common :: NixCommonConfig
130+ , _nixInstantiateConfig_eval :: Bool
132+makeLenses ''NixInstantiateConfig
134+instance HasNixCommonConfig NixInstantiateConfig where
135+ nixCommonConfig = nixInstantiateConfig_common
137+instance Default NixInstantiateConfig where
138+ def = NixInstantiateConfig def False
108−-- | If a nix command fails, and this may be related to the NIX_REMOTE issue,
140+runNixInstantiateConfig :: NixInstantiateConfig -> [FilePath]
109−-- tell the user what to do.
141+runNixInstantiateConfig cfg = mconcat
110−--
142+ [ runNixCommonConfig $ cfg ^. nixCommonConfig
111−-- Added: June, 2018. Consider removing this eventually.
143+ , "--eval" <$ guard (_nixInstantiateConfig_eval cfg)
112−withNixRemoteCheck
144+ ]
147+ = NixCmd_Build NixBuildConfig
148+ | NixCmd_Instantiate NixInstantiateConfig
150+instance Default NixCmd where
151+ def = NixCmd_Build def
113− :: MonadObelisk m
153+nixCmd :: MonadObelisk m => NixCmd -> m FilePath
114− => (forall m'. MonadInfallibleObelisk m' => ExceptT ObeliskError m' a)
154+nixCmd cmdCfg = withSpinner' ("Running " <> cmd <> " on " <> desc) (Just $ const $ "Built " <> desc) $ do
115− -> m a
155+ output <- readProcessAndLogStderr Debug $ proc (T.unpack cmd) $ options
116−withNixRemoteCheck f = do
156+ -- Remove final newline that Nix appends
117− status <- runExceptT f
157+ Just (outPath, '\n') <- pure $ T.unsnoc output
118− case status of
158+ pure $ T.unpack outPath
119− Right a -> pure a
159+ where
120− Left e -> throwError =<< case matching asProcessFailure e of
160+ (cmd, options, commonCfg) = case cmdCfg of
121− Left _ -> pure e
161+ NixCmd_Build cfg' ->
122− Right pf -> liftIO (lookupEnv "NIX_REMOTE") >>= \case
162+ ( "nix-build"
123− Just _ -> pure e
163+ , runNixBuildConfig cfg'
124− Nothing -> liftIO (writable <$> getPermissions "/nix/var/nix/db") >>= \case
164+ , cfg' ^. nixCommonConfig
125− True -> pure e
165+ )
126− False -> pure $ ObeliskError_ProcessError pf $ Just $ T.unlines
166+ NixCmd_Instantiate cfg' ->
127− [ "!!! "
167+ ( "nix-instantiate"
128− , "!!! A nix command failed to run. You might need to set the NIX_REMOTE environment variable"
168+ , runNixInstantiateConfig cfg'
129− , "!!! to `daemon`. To do this, run the following before running obelisk:"
169+ , cfg' ^. nixCommonConfig
131− , "!!! export NIX_REMOTE=daemon"
171+ path = commonCfg ^. nixCmdConfig_target . target_path
132− , "!!! "
172+ desc = T.pack $ path <> maybe ""
133− , "!!! For details, see https://github.com/NixOS/nixpkgs/issues/5713"
173+ (\a -> " [" <> a <> "]")
134− , "!!! "
174+ (commonCfg ^. nixCmdConfig_target . target_attr)
lib/command/src/Obelisk/Command/Project.hs+2−4
@@ -34,7 +34,6 @@ import GitHub.Data.Name (Name)
34import Obelisk.App (MonadObelisk)
34import Obelisk.App (MonadObelisk)
35import Obelisk.CliApp
35import Obelisk.CliApp
36import Obelisk.Command.Thunk
36import Obelisk.Command.Thunk
37−import Obelisk.Command.Nix (withNixRemoteCheck)
38--TODO: Make this module resilient to random exceptions
37--TODO: Make this module resilient to random exceptions
40--TODO: Don't hardcode this
39--TODO: Don't hardcode this
@@ -48,7 +47,6 @@ obeliskSourceWithBranch branch = ThunkSource_GitHub $ GitHubSource
48 { _gitHubSource_owner = "obsidiansystems"
47 { _gitHubSource_owner = "obsidiansystems"
49 , _gitHubSource_repo = "obelisk"
48 , _gitHubSource_repo = "obelisk"
50 , _gitHubSource_branch = Just branch
49 , _gitHubSource_branch = Just branch
51− , _gitHubSource_private = False
54data InitSource
52data InitSource
@@ -147,7 +145,7 @@ findProjectRoot target = do
147 (result, _) <- liftIO $ runStateT (walkToProjectRoot target targetStat myUid) []
145 (result, _) <- liftIO $ runStateT (walkToProjectRoot target targetStat myUid) []
148 return result
146 return result
150−withProjectRoot :: MonadObelisk m => FilePath -> (FilePath -> m ()) -> m ()
148+withProjectRoot :: MonadObelisk m => FilePath -> (FilePath -> m a) -> m a
151withProjectRoot target f = findProjectRoot target >>= \case
149withProjectRoot target f = findProjectRoot target >>= \case
152 Nothing -> failWith "Must be used inside of an Obelisk project"
150 Nothing -> failWith "Must be used inside of an Obelisk project"
153 Just root -> f root
151 Just root -> f root
@@ -205,7 +203,7 @@ inImpureProjectShell shellName command = withProjectRoot "." $ \root ->
205 projectShell root False shellName command
203 projectShell root False shellName command
207projectShell :: MonadObelisk m => FilePath -> Bool -> String -> String -> m ()
205projectShell :: MonadObelisk m => FilePath -> Bool -> String -> String -> m ()
208−projectShell root isPure shellName command = withNixRemoteCheck $ do
206+projectShell root isPure shellName command = do
209 (_, _, _, ph) <- createProcess_ "runNixShellAttr" $ setCwd (Just root) $ proc "nix-shell" $
207 (_, _, _, ph) <- createProcess_ "runNixShellAttr" $ setCwd (Just root) $ proc "nix-shell" $
210 [ "--pure" | isPure ] <>
208 [ "--pure" | isPure ] <>
lib/command/src/Obelisk/Command/Run.hs+20−5
@@ -26,16 +26,19 @@ import Hpack.Config
26import Hpack.Render
26import Hpack.Render
27import Hpack.Yaml
27import Hpack.Yaml
28import Language.Haskell.Extension
28import Language.Haskell.Extension
29−import Network.Socket
29+import Network.Socket hiding (Debug)
30import System.Directory
30import System.Directory
31import System.FilePath
31import System.FilePath
32+import System.Process (proc)
32import System.IO.Temp (withSystemTempDirectory)
33import System.IO.Temp (withSystemTempDirectory)
33import Data.ByteString (ByteString)
34import Data.ByteString (ByteString)
35import Obelisk.App (MonadObelisk, ObeliskT)
36import Obelisk.App (MonadObelisk, ObeliskT)
38+ ( CliT (..), HasCliConfig, Severity (..)
36−import Obelisk.CliApp (CliT (..), HasCliConfig, Severity (..), callCommand, failWith, getCliConfig, putLog,
39+ , callCommand, failWith, getCliConfig, putLog
37− runCli)
40+ , readProcessAndLogStderr, runCli)
38−import Obelisk.Command.Project (inProjectShell)
41+import Obelisk.Command.Project (inProjectShell, withProjectRoot)
40data CabalPackageInfo = CabalPackageInfo
43data CabalPackageInfo = CabalPackageInfo
41 { _cabalPackageInfo_packageRoot :: FilePath
44 { _cabalPackageInfo_packageRoot :: FilePath
@@ -51,7 +54,19 @@ run = do
51 pkgs <- getLocalPkgs
54 pkgs <- getLocalPkgs
52 withGhciScript pkgs $ \dotGhciPath -> do
55 withGhciScript pkgs $ \dotGhciPath -> do
53 freePort <- getFreePort
56 freePort <- getFreePort
57+ assets <- withProjectRoot "." $ \root ->
58+ -- `--raw` is not available with old nix-instantiate. It drops quotation
59+ -- marks and trailing newline, so is very convenient for shelling out.
60+ readProcessAndLogStderr Debug $
61+ proc "nix" ["eval", "-f", root, "passthru.staticFilesImpure", "--raw"]
62+ putLog Debug $ "Assets impurely loaded from: " <> assets
54− runGhcid dotGhciPath $ Just $ unwords ["run", show freePort, "Backend.backend", "Frontend.frontend"]
63+ runGhcid dotGhciPath $ Just $ unwords
66+ , "(runServeAsset " ++ show assets ++ ")"
68+ , "Frontend.frontend"
56runRepl :: MonadObelisk m => m ()
71runRepl :: MonadObelisk m => m ()
57runRepl = do
72runRepl = do
lib/command/src/Obelisk/Command/Thunk.hs+356−272
@@ -27,10 +27,14 @@ module Obelisk.Command.Thunk
27 , updateThunk
27 , updateThunk
28 , getThunkPtr
28 , getThunkPtr
29 , getThunkPtr'
29 , getThunkPtr'
32import Control.Applicative
34import Control.Applicative
33−import Control.Exception (displayException, throwIO, try)
35+import Control.Exception (displayException, try)
36+import qualified Control.Lens as Lens
37+import Control.Lens.Indexed hiding ((<.>))
34import Control.Monad
38import Control.Monad
35import Control.Monad.Catch (handle)
39import Control.Monad.Catch (handle)
36import Control.Monad.Except
40import Control.Monad.Except
@@ -40,13 +44,13 @@ import Data.Aeson.Encode.Pretty
40import qualified Data.Aeson.Types as Aeson
44import qualified Data.Aeson.Types as Aeson
41import qualified Data.ByteString.Lazy as LBS
45import qualified Data.ByteString.Lazy as LBS
42import Data.Default
46import Data.Default
43−import Data.Either.Combinators (rightToMaybe)
47+import Data.Either.Combinators (fromRight', rightToMaybe)
45import Data.Git.Ref (Ref)
48import Data.Git.Ref (Ref)
46import qualified Data.Git.Ref as Ref
49import qualified Data.Git.Ref as Ref
47import qualified Data.List as L
50import qualified Data.List as L
48import Data.List.NonEmpty (NonEmpty (..))
51import Data.List.NonEmpty (NonEmpty (..))
49import qualified Data.List.NonEmpty as NonEmpty
52import qualified Data.List.NonEmpty as NonEmpty
50import qualified Data.Map as Map
54import qualified Data.Map as Map
51import Data.Maybe
55import Data.Maybe
52import Data.Set (Set)
56import Data.Set (Set)
@@ -56,12 +60,9 @@ import qualified Data.Text as T
56import Data.Text.Encoding
60import Data.Text.Encoding
57import qualified Data.Text.IO as T
61import qualified Data.Text.IO as T
58import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
62import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
59−import Data.Yaml (parseMaybe, (.:))
63+import Data.Yaml (parseMaybe)
60−import qualified Data.Yaml as Yaml
61import GitHub
64import GitHub
62import GitHub.Data.Name
65import GitHub.Data.Name
63−import GitHub.Endpoints.Repos.Contents (archiveForR)
65import Obelisk.Command.Nix
66import Obelisk.Command.Nix
66import System.Directory
67import System.Directory
67import System.FilePath
68import System.FilePath
@@ -69,10 +70,10 @@ import System.IO.Error
69import System.IO.Temp
70import System.IO.Temp
70import System.Posix (getSymbolicLinkStatus, modificationTime)
71import System.Posix (getSymbolicLinkStatus, modificationTime)
71import System.Process (proc)
72import System.Process (proc)
73import Obelisk.App (MonadObelisk)
75import Obelisk.App (MonadObelisk)
74import Obelisk.CliApp
76import Obelisk.CliApp
75−import Obelisk.Command.Nix (withNixRemoteCheck)
76import Obelisk.Command.Utils
77import Obelisk.Command.Utils
78--TODO: Support symlinked thunk data
79--TODO: Support symlinked thunk data
@@ -111,21 +112,43 @@ data GitHubSource = GitHubSource
111 { _gitHubSource_owner :: Name Owner
112 { _gitHubSource_owner :: Name Owner
112 , _gitHubSource_repo :: Name Repo
113 , _gitHubSource_repo :: Name Repo
113 , _gitHubSource_branch :: Maybe (Name Branch)
114 , _gitHubSource_branch :: Maybe (Name Branch)
114− , _gitHubSource_private :: Bool
116 deriving (Show, Eq, Ord)
116 deriving (Show, Eq, Ord)
118data GitSource = GitSource
118data GitSource = GitSource
119 { _gitSource_url :: URI
119 { _gitSource_url :: URI
120− , _gitSource_branch :: Name Branch
120+ , _gitSource_branch :: Maybe (Name Branch)
121 , _gitSource_fetchSubmodules :: Bool
121 , _gitSource_fetchSubmodules :: Bool
123 deriving (Show, Eq, Ord)
123 deriving (Show, Eq, Ord)
125+-- | Convert a GitHub source to a regular Git source. Assumes no submodules.
126+forgetGithub :: Bool -> GitHubSource -> GitSource
127+forgetGithub useSsh s = GitSource
128+ { _gitSource_url = URI
129+ { uriScheme = Just $ fromRight' $ mkScheme $ if useSsh then "ssh" else "https"
130+ , uriAuthority = Right $ Authority
131+ { authUserInfo = UserInfo (fromRight' $ mkUsername "git") Nothing
133+ , authHost = fromRight' $ mkHost "github.com"
134+ , authPort = Nothing
136+ , uriPath = Just ( False
137+ , fromRight' . mkPathPiece <$>
138+ untagName (_gitHubSource_owner s)
139+ :| [ untagName (_gitHubSource_repo s) <> ".git" ]
142+ , uriFragment = Nothing
144+ , _gitSource_branch = _gitHubSource_branch s
145+ , _gitSource_fetchSubmodules = False
125getThunkGitBranch :: ThunkPtr -> Maybe Text
148getThunkGitBranch :: ThunkPtr -> Maybe Text
126getThunkGitBranch (ThunkPtr _ src) = fmap untagName $ case src of
149getThunkGitBranch (ThunkPtr _ src) = fmap untagName $ case src of
127 ThunkSource_GitHub s -> _gitHubSource_branch s
150 ThunkSource_GitHub s -> _gitHubSource_branch s
128− ThunkSource_Git s -> Just $ _gitSource_branch s
151+ ThunkSource_Git s -> _gitSource_branch s
130commitNameToRef :: Name Commit -> Ref
153commitNameToRef :: Name Commit -> Ref
131commitNameToRef (N c) = Ref.fromHex $ encodeUtf8 c
154commitNameToRef (N c) = Ref.fromHex $ encodeUtf8 c
@@ -136,16 +159,17 @@ getNixSha256ForUriUnpacked
137 -> m NixSha256
160 -> m NixSha256
138getNixSha256ForUriUnpacked uri =
161getNixSha256ForUriUnpacked uri =
139− withExitFailMessage ("nix-prefetch-url: Failed to determine sha256 hash of URL " <> T.pack (show uri)) $ do
162+ withExitFailMessage ("nix-prefetch-url: Failed to determine sha256 hash of URL " <> render uri) $ do
140− withNixRemoteCheck $ readProcessAndLogStderr Debug $
163+ [hash] <- fmap T.lines $ readProcessAndLogOutput (Debug, Debug) $
141− proc "nix-prefetch-url" ["--unpack" , "--type" , "sha256" , show uri]
164+ proc "nix-prefetch-url" ["--unpack" , "--type" , "sha256" , T.unpack $ render uri]
143nixPrefetchGit :: MonadObelisk m => URI -> Text -> Bool -> m NixSha256
167nixPrefetchGit :: MonadObelisk m => URI -> Text -> Bool -> m NixSha256
144nixPrefetchGit uri rev fetchSubmodules =
168nixPrefetchGit uri rev fetchSubmodules =
145− withExitFailMessage ("nix-prefetch-git: Failed to determine sha256 hash of Git repo " <> T.pack (show uri) <> " at " <> rev) $ do
169+ withExitFailMessage ("nix-prefetch-git: Failed to determine sha256 hash of Git repo " <> render uri <> " at " <> rev) $ do
146− out <- withNixRemoteCheck $ readProcessAndLogStderr Debug $
170+ out <- readProcessAndLogStderr Debug $
147 proc "nix-prefetch-git" $ filter (/="")
171 proc "nix-prefetch-git" $ filter (/="")
148− [ "--url", show uri
172+ [ "--url", T.unpack $ render uri
149 , "--rev", T.unpack rev
173 , "--rev", T.unpack rev
150 , if fetchSubmodules then "--fetch-submodules" else ""
174 , if fetchSubmodules then "--fetch-submodules" else ""
151 , "--quiet"
175 , "--quiet"
@@ -155,56 +179,6 @@ nixPrefetchGit uri rev fetchSubmodules =
155 Nothing -> failWith $ "nix-prefetch-git: unrecognized output " <> out
179 Nothing -> failWith $ "nix-prefetch-git: unrecognized output " <> out
156 Just x -> pure x
180 Just x -> pure x
158−getLatestGitRev :: MonadObelisk m => GitSource -> m ThunkRev
159−getLatestGitRev s = withSystemTempDirectory "git-clone" $ \tmpDir -> do
160− withExitFailMessage ("Unable to determine latest git revision for branch " <> branch) $ do
161− let git = readProcessAndLogStderr Debug . gitProc tmpDir
163− (git ["clone", "--no-checkout", show $ _gitSource_url s]) -- Might be able to use --bare here instead to go faster.
164− (git ["log", T.unpack branch, "--max-count=1", "--format=%H"])
166− case T.strip <$> safeLast (T.lines out) of
167− Nothing -> failWith $ "Unable to parse git log: " <> out
169− putLog Debug $ "Latest commit in " <> branch <> " is " <> rev
170− sha <- nixPrefetchGit (_gitSource_url s) rev (_gitSource_fetchSubmodules s)
171− putLog Debug $ "Nix sha256 is " <> sha
173− { _thunkRev_commit = Ref.fromHexString $ T.unpack rev
174− , _thunkRev_nixSha256 = sha
177− remote :: Text = "origin"
178− branch :: Text = remote <> "/" <> untagName (_gitSource_branch s)
180− safeLast [] = Nothing
181− safeLast xs = Just $ last xs
183−-- | Get the latest revision available from the given source
184−getLatestRev :: MonadObelisk m => ThunkSource -> m ThunkRev
186− ThunkSource_GitHub s -> do
187− auth <- liftIO $ getHubAuth "github.com"
188− commitsResult <- liftIO $ executeRequestMaybe auth $ commitsWithOptionsForR
189− (_gitHubSource_owner s)
190− (_gitHubSource_repo s)
192− $ case _gitHubSource_branch s of
194− Just b -> [CommitQuerySha $ untagName b]
195− commitInfos <- either (liftIO . throwIO) return commitsResult
196− commitInfo : _ <- return $ toList commitInfos
197− let commit = commitSha commitInfo
198− putLog Debug $ "Latest commit is " <> untagName commit
199− Right archiveUri <- liftIO $ executeRequestMaybe auth $ archiveForR (_gitHubSource_owner s) (_gitHubSource_repo s) ArchiveFormatTarball $ Just $ untagName commit
200− nixSha256 <- getNixSha256ForUriUnpacked archiveUri
201− putLog Debug $ "Nix sha256 is " <> nixSha256
203− { _thunkRev_commit = commitNameToRef commit
204− , _thunkRev_nixSha256 = nixSha256
206− ThunkSource_Git s -> getLatestGitRev s
208--TODO: Pretty print these
182--TODO: Pretty print these
209data ReadThunkError
183data ReadThunkError
210 = ReadThunkError_UnrecognizedFiles
184 = ReadThunkError_UnrecognizedFiles
@@ -313,18 +287,16 @@ parseGitHubSource v = do
313 owner <- v Aeson..: "owner"
287 owner <- v Aeson..: "owner"
314 repo <- v Aeson..: "repo"
288 repo <- v Aeson..: "repo"
315 branch <- v Aeson..:! "branch"
289 branch <- v Aeson..:! "branch"
316− mPrivate <- v Aeson..:! "private"
317 pure $ GitHubSource
290 pure $ GitHubSource
318 { _gitHubSource_owner = owner
291 { _gitHubSource_owner = owner
319 , _gitHubSource_repo = repo
292 , _gitHubSource_repo = repo
320 , _gitHubSource_branch = branch
293 , _gitHubSource_branch = branch
321− , _gitHubSource_private = fromMaybe False mPrivate
324parseGitSource :: Aeson.Object -> Aeson.Parser GitSource
296parseGitSource :: Aeson.Object -> Aeson.Parser GitSource
325parseGitSource v = do
297parseGitSource v = do
326 Just url <- parseGitUri <$> v Aeson..: "url"
298 Just url <- parseGitUri <$> v Aeson..: "url"
327− branch <- v Aeson..: "branch"
299+ branch <- v Aeson..:! "branch"
328 fetchSubmodules <- v Aeson..:! "fetchSubmodules"
300 fetchSubmodules <- v Aeson..:! "fetchSubmodules"
329 pure $ GitSource
301 pure $ GitSource
330 { _gitSource_url = url
302 { _gitSource_url = url
@@ -353,20 +325,14 @@ encodeThunkPtrData (ThunkPtr rev src) = case src of
353 ThunkSource_GitHub s -> encodePretty' githubCfg $ Aeson.object $ catMaybes
325 ThunkSource_GitHub s -> encodePretty' githubCfg $ Aeson.object $ catMaybes
354 [ Just $ "owner" .= _gitHubSource_owner s
326 [ Just $ "owner" .= _gitHubSource_owner s
355 , Just $ "repo" .= _gitHubSource_repo s
327 , Just $ "repo" .= _gitHubSource_repo s
356− , case _gitHubSource_branch s of
328+ , ("branch" .=) <$> _gitHubSource_branch s
357− Just b -> Just $ "branch" .= b
359− , if _gitHubSource_private s
360− then Just $ "private" .= True
362 , Just $ "rev" .= Ref.toHexString (_thunkRev_commit rev)
329 , Just $ "rev" .= Ref.toHexString (_thunkRev_commit rev)
363 , Just $ "sha256" .= _thunkRev_nixSha256 rev
330 , Just $ "sha256" .= _thunkRev_nixSha256 rev
365 ThunkSource_Git s -> encodePretty' plainGitCfg $ Aeson.object $ catMaybes
332 ThunkSource_Git s -> encodePretty' plainGitCfg $ Aeson.object $ catMaybes
366− --TODO: Is this safe? read/show is jank for `URI`
367− [ Just $ "url" .= show (_gitSource_url s)
333+ [ Just $ "url" .= render (_gitSource_url s)
368 , Just $ "rev" .= Ref.toHexString (_thunkRev_commit rev)
334 , Just $ "rev" .= Ref.toHexString (_thunkRev_commit rev)
369− , Just $ "branch" .= _gitSource_branch s
335+ , ("branch" .=) <$> _gitSource_branch s
370 , Just $ "sha256" .= _thunkRev_nixSha256 rev
336 , Just $ "sha256" .= _thunkRev_nixSha256 rev
371 , Just $ "fetchSubmodules" .= _gitSource_fetchSubmodules s
337 , Just $ "fetchSubmodules" .= _gitSource_fetchSubmodules s
@@ -498,20 +464,6 @@ plainGitStandaloneLoaderV2 = T.unlines
498thunkFileNames :: [FilePath]
464thunkFileNames :: [FilePath]
499thunkFileNames = ["default.nix", "github.json", "git.json"]
465thunkFileNames = ["default.nix", "github.json", "git.json"]
501−-- | Look for authentication info from the 'hub' command
503− :: Text -- ^ Domain name
505−getHubAuth domain = do
506− hubConfig <- getXdgDirectory XdgConfig "hub"
507− Yaml.decodeFileEither hubConfig >>= \case
508− Left _ -> return Nothing
509− Right v -> return $ flip parseMaybe v $ \v' -> do
510− Yaml.Array domainConfigs <- v' .: domain --TODO: Determine what multiple domainConfigs means
511− [Yaml.Object domainConfig] <- return $ toList domainConfigs
512− token <- domainConfig .: "oauth_token"
513− return $ OAuth $ encodeUtf8 token
515--TODO: when checking something out, make a shallow clone
467--TODO: when checking something out, make a shallow clone
517-- | Checks a cache directory to see if there is a fresh symlink
469-- | Checks a cache directory to see if there is a fresh symlink
@@ -550,13 +502,12 @@ nixBuildThunkAttrWithCache thunkDir attr = do
550 Just c -> return c
502 Just c -> return c
551 Nothing -> do
503 Nothing -> do
552 putLog Warning $ T.pack $ mconcat [thunkDir, ": ", attr, " not cached, building ..."]
504 putLog Warning $ T.pack $ mconcat [thunkDir, ": ", attr, " not cached, building ..."]
553− _ <- nixBuild $ def
505+ _ <- nixCmd $ NixCmd_Build$ def
554− { _nixBuildConfig_target = Target
506+ Lens.& nixBuildConfig_outLink Lens..~ OutLink_IndirectRoot cachePath
507+ Lens.& nixCmdConfig_target Lens..~ Target
555 { _target_path = thunkDir
508 { _target_path = thunkDir
556 , _target_attr = Just attr
509 , _target_attr = Just attr
558− , _nixBuildConfig_outLink = OutLink_IndirectRoot cachePath
560 return cachePath
511 return cachePath
562-- | Build a nix attribute, and cache the result if possible
513-- | Build a nix attribute, and cache the result if possible
@@ -572,13 +523,12 @@ nixBuildAttrWithCache exprPath attr = do
572 readThunk exprPath >>= \case
523 readThunk exprPath >>= \case
573 -- Only packed thunks are cached. in particular, checkouts are not
524 -- Only packed thunks are cached. in particular, checkouts are not
574 Right (ThunkData_Packed _) -> nixBuildThunkAttrWithCache exprPath attr
525 Right (ThunkData_Packed _) -> nixBuildThunkAttrWithCache exprPath attr
575− _ -> nixBuild $ def
526+ _ -> nixCmd $ NixCmd_Build $ def
576− { _nixBuildConfig_target = Target
527+ Lens.& nixBuildConfig_outLink Lens..~ OutLink_None
528+ Lens.& nixCmdConfig_target Lens..~ Target
577 { _target_path = exprPath
529 { _target_path = exprPath
578 , _target_attr = Just attr
530 , _target_attr = Just attr
580− , _nixBuildConfig_outLink = OutLink_None
583-- | Safely update thunk using a custom action
533-- | Safely update thunk using a custom action
@@ -590,7 +540,7 @@ updateThunk p f = withSystemTempDirectory "obelisk-thunkptr-" $ \tmpDir -> do
590 p' <- copyThunkToTmp tmpDir p
540 p' <- copyThunkToTmp tmpDir p
591 unpackThunk' True p'
541 unpackThunk' True p'
592 result <- f p'
542 result <- f p'
593− updateThunkFromTmp p' "origin" -- TODO: stop hardcoding remote
543+ updateThunkFromTmp p'
594 return result
544 return result
596 copyThunkToTmp tmpDir thunkDir = readThunk thunkDir >>= \case
546 copyThunkToTmp tmpDir thunkDir = readThunk thunkDir >>= \case
@@ -601,8 +551,8 @@ updateThunk p f = withSystemTempDirectory "obelisk-thunkptr-" $ \tmpDir -> do
601 proc "cp" ["-r", "-T", thunkDir, tmpThunk]
551 proc "cp" ["-r", "-T", thunkDir, tmpThunk]
602 return tmpThunk
552 return tmpThunk
603 Right _ -> failWith $ "Thunk is not packed"
553 Right _ -> failWith $ "Thunk is not packed"
604− updateThunkFromTmp p' remote = do
554+ updateThunkFromTmp p' = do
605− packThunk' True p' remote
555+ _ <- packThunk' True p'
606 callProcessAndLogOutput (Notice, Error) $
556 callProcessAndLogOutput (Notice, Error) $
607 proc "cp" ["-r", "-T", p', p]
557 proc "cp" ["-r", "-T", p', p]
@@ -612,8 +562,16 @@ finalMsg noTrail s = if noTrail then Nothing else Just s
612unpackThunk :: MonadObelisk m => FilePath -> m ()
562unpackThunk :: MonadObelisk m => FilePath -> m ()
613unpackThunk = unpackThunk' False
563unpackThunk = unpackThunk' False
565+-- | Check that we are not somewhere inside the thunk directory
566+checkThunkDirectory :: MonadObelisk m => FilePath -> m ()
567+checkThunkDirectory thunkDir = do
568+ currentDir <- liftIO getCurrentDirectory
569+ thunkDir' <- liftIO $ canonicalizePath thunkDir
570+ when (thunkDir' `L.isInfixOf` currentDir) $
571+ failWith "Can't pack/unpack from within the thunk directory"
615unpackThunk' :: MonadObelisk m => Bool -> FilePath -> m ()
573unpackThunk' :: MonadObelisk m => Bool -> FilePath -> m ()
616−unpackThunk' noTrail thunkDir = readThunk thunkDir >>= \case
574+unpackThunk' noTrail thunkDir = checkThunkDirectory thunkDir >> readThunk thunkDir >>= \case
617 Left err -> failWith $ "thunk unpack: " <> T.pack (show err)
575 Left err -> failWith $ "thunk unpack: " <> T.pack (show err)
618 --TODO: Overwrite option that rechecks out thunk; force option to do so even if working directory is dirty
576 --TODO: Overwrite option that rechecks out thunk; force option to do so even if working directory is dirty
619 Right (ThunkData_Checkout _) -> failWith "thunk unpack: thunk is already unpacked"
577 Right (ThunkData_Checkout _) -> failWith "thunk unpack: thunk is already unpacked"
@@ -621,190 +579,316 @@ unpackThunk' noTrail thunkDir = readThunk thunkDir >>= \case
621 let (thunkParent, thunkName) = splitFileName thunkDir
579 let (thunkParent, thunkName) = splitFileName thunkDir
622 withTempDirectory thunkParent thunkName $ \tmpRepo -> do
580 withTempDirectory thunkParent thunkName $ \tmpRepo -> do
623 let obGitDir = tmpRepo </> ".git" </> "obelisk"
581 let obGitDir = tmpRepo </> ".git" </> "obelisk"
624− case _thunkPtr_source tptr of
582+ s = case _thunkPtr_source tptr of
625− ThunkSource_GitHub s -> do
583+ ThunkSource_GitHub s' -> forgetGithub False s'
626− mauth <- liftIO $ getHubAuth "github.com"
627− repoResult <- liftIO $ executeRequestMaybe mauth $ repositoryR (_gitHubSource_owner s) (_gitHubSource_repo s)
628− githubURI <- either (liftIO . throwIO) (return . repoSshUrl) repoResult >>= \case
629− Nothing -> failWith "Cannot determine clone URI for thunk source"
630− Just c -> return $ T.unpack $ getUrl c
632− withSpinner' ("Fetching thunk " <> T.pack thunkDir)
633− ( finalMsg noTrail $ const $ "Fetched thunk " <> T.pack thunkDir) $ do
634− callProcessAndLogOutput (Debug, Debug) $
635− proc "hub" ["clone", "-n", githubURI, tmpRepo]
636− --If this directory already exists then something is weird and we should fail
637− liftIO $ createDirectory obGitDir
638− callProcessAndLogOutput (Debug, Error) $
639− proc "cp" ["-r", "-T", thunkDir </> ".", obGitDir </> "orig-thunk"]
642− putLog Debug $ "Checking out " <> T.pack (show $ maybe "" untagName $ _gitHubSource_branch s)
643− callProcessAndLogOutput (Debug, Debug) $
647− , maybe [] (\n -> ["-B", T.unpack (untagName n)]) (_gitHubSource_branch s)
648− , pure $ Ref.toHexString $ _thunkRev_commit $ _thunkPtr_rev tptr
650− -- Set upstream branch
651− forM_ (_gitHubSource_branch s) $ \branch ->
652− callProcessAndLogOutput (Debug, Error) $
653− proc "hub" ["-C", tmpRepo, "branch", "-u", "origin/" <> T.unpack (untagName branch)]
654− callProcessAndLogOutput (Notice, Error) $ proc "rm" ["-r", thunkDir]
655− callProcessAndLogOutput (Notice, Error) $ proc "mv" ["-T", tmpRepo, thunkDir]
657− ThunkSource_Git s -> do
584+ ThunkSource_Git s' -> s'
658− withSpinner' ("Fetching thunk " <> T.pack thunkName)
585+ withSpinner' ("Fetching thunk " <> T.pack thunkName)
659− (finalMsg noTrail $ const $ "Fetched thunk " <> T.pack thunkName) $ do
586+ (finalMsg noTrail $ const $ "Fetched thunk " <> T.pack thunkName) $ do
660− let git = callProcessAndLogOutput (Notice, Notice) . gitProc tmpRepo
587+ let git = callProcessAndLogOutput (Notice, Notice) . gitProc tmpRepo
661− git ["clone", if _gitSource_fetchSubmodules s then "--recursive" else "", show (_gitSource_url s)]
589+ ++ ("--recursive" <$ guard (_gitSource_fetchSubmodules s))
590+ ++ [ T.unpack $ render $ _gitSource_url s ]
591+ ++ do branch <- maybeToList $ _gitSource_branch s
592+ [ "--branch", T.unpack $ untagName branch ]
662− git ["reset", "--hard", Ref.toHexString $ _thunkRev_commit $ _thunkPtr_rev tptr]
593+ git ["reset", "--hard", Ref.toHexString $ _thunkRev_commit $ _thunkPtr_rev tptr]
663− when (_gitSource_fetchSubmodules s) $
594+ when (_gitSource_fetchSubmodules s) $
664− git ["submodule", "update", "--recursive", "--init"]
595+ git ["submodule", "update", "--recursive", "--init"]
665− git ["branch", "-u", "origin/" <> T.unpack (untagName $ _gitSource_branch s)]
596+
667− liftIO $ createDirectory obGitDir
597+ liftIO $ createDirectory obGitDir
668− callProcessAndLogOutput (Notice, Error) $
598+ callProcessAndLogOutput (Notice, Error) $
669− proc "cp" ["-r", "-T", thunkDir </> ".", obGitDir </> "orig-thunk"]
599+ proc "cp" ["-r", "-T", thunkDir </> ".", obGitDir </> "orig-thunk"]
670− callProcessAndLogOutput (Notice, Error) $
600+ callProcessAndLogOutput (Notice, Error) $
671− proc "rm" ["-r", thunkDir]
601+ proc "rm" ["-r", thunkDir]
672− callProcessAndLogOutput (Notice, Error) $
602+ callProcessAndLogOutput (Notice, Error) $
673− proc "mv" ["-T", tmpRepo, thunkDir]
603+ proc "mv" ["-T", tmpRepo, thunkDir]
675--TODO: add force mode to pack even if changes are present
605--TODO: add force mode to pack even if changes are present
676--TODO: add a rollback mode to pack to the original thunk
606--TODO: add a rollback mode to pack to the original thunk
677−packThunk :: MonadObelisk m => FilePath -> Text -> m ()
607+packThunk :: MonadObelisk m => FilePath -> m ThunkPtr
678packThunk = packThunk' False
608packThunk = packThunk' False
680−packThunk' :: MonadObelisk m => Bool -> FilePath -> Text -> m ()
610+packThunk' :: MonadObelisk m => Bool -> FilePath -> m ThunkPtr
681−packThunk' noTrail thunkDir upstream = readThunk thunkDir >>= \case
611+packThunk' noTrail thunkDir = checkThunkDirectory thunkDir >> readThunk thunkDir >>= \case
682 Left err -> failWith $ T.pack $ "thunk pack: " <> show err
612 Left err -> failWith $ T.pack $ "thunk pack: " <> show err
683 Right (ThunkData_Packed _) -> failWith "pack: thunk is already packed"
613 Right (ThunkData_Packed _) -> failWith "pack: thunk is already packed"
684 Right (ThunkData_Checkout _) -> do
614 Right (ThunkData_Checkout _) -> do
685 withSpinner' ("Packing thunk " <> T.pack thunkDir)
615 withSpinner' ("Packing thunk " <> T.pack thunkDir)
686 (finalMsg noTrail $ const $ "Packed thunk " <> T.pack thunkDir) $ do
616 (finalMsg noTrail $ const $ "Packed thunk " <> T.pack thunkDir) $ do
687− thunkPtr <- getThunkPtr thunkDir upstream
617+ thunkPtr <- getThunkPtr thunkDir
688 callProcessAndLogOutput (Debug, Error) $ proc "rm" ["-rf", thunkDir]
618 callProcessAndLogOutput (Debug, Error) $ proc "rm" ["-rf", thunkDir]
689 liftIO $ createThunk thunkDir thunkPtr
619 liftIO $ createThunk thunkDir thunkPtr
691−getThunkPtr :: MonadObelisk m => FilePath -> Text -> m ThunkPtr
622+getThunkPtr :: MonadObelisk m => FilePath -> m ThunkPtr
692getThunkPtr = getThunkPtr' True
623getThunkPtr = getThunkPtr' True
694−getThunkPtr' :: MonadObelisk m => Bool -> FilePath -> Text -> m ThunkPtr
625+getThunkPtr' :: forall m. MonadObelisk m => Bool -> FilePath -> m ThunkPtr
695−getThunkPtr' checkClean thunkDir upstream = do
626+getThunkPtr' checkClean thunkDir = do
696− when checkClean $ ensureCleanGitRepo thunkDir True $
627+ when checkClean $ ensureCleanGitRepo thunkDir True $
697− "thunk pack: thunk checkout contains unsaved modifications"
628+ "thunk pack: thunk checkout contains unsaved modifications"
699− -- Check whether there are any stashes
630+ -- Check whether there are any stashes
700− stashOutput <- readGitProcess thunkDir ["stash", "list"]
631+ stashOutput <- readGitProcess thunkDir ["stash", "list"]
701− when checkClean $ case T.null stashOutput of
632+ when checkClean $ case T.null stashOutput of
702− False -> do
633+ False -> do
703− failWith $ T.unlines $
634+ failWith $ T.unlines $
704− [ "thunk pack: thunk checkout has stashes"
635+ [ "thunk pack: thunk checkout has stashes"
705− , "git stash list:"
636+ , "git stash list:"
706− ] ++ T.lines stashOutput
637+ ] ++ T.lines stashOutput
707− True -> return ()
638+ True -> return ()
709− --Check whether all local heads are pushed
640+ -- Get information on all branches and their (optional) designated upstream
710− repoHeads <- T.lines <$> readGitProcess thunkDir ["for-each-ref", "--format=%(refname:short)", "refs/heads/"]
642+ (headDump :: [Text]) <- T.lines <$> readGitProcess thunkDir
711− remotes <- T.lines <$> readGitProcess thunkDir ["remote"]
643+ [ "for-each-ref"
712− --Check that the upstream specified actually exists
644+ , "--format=%(refname:short) %(upstream:short) %(upstream:remotename)"
713− case L.find (== upstream) remotes of
645+ , "refs/heads/"
714− Nothing -> failWith $ "thunk pack: upstream " <> upstream <> " does not exist. Available upstreams are " <> T.intercalate ", " remotes
646+ ]
715− Just _ -> return ()
647+
716− -- iterate over cartesian product
648+ (headInfo :: Map Text (Maybe (Text, Text)))
649+ <- fmap Map.fromList $ forM headDump $ \line -> do
650+ (branch : restOfLine) <- pure $ T.words line
651+ mUpstream <- case restOfLine of
653+ [u, r] -> pure $ Just (u, r)
654+ (_:_) -> failWith "git for-each-ref invalid output"
655+ pure (branch, mUpstream)
657+ putLog Debug $ "branches: " <> T.pack (show headInfo)
659+ let errorMap :: Map Text ()
660+ headUpstream :: Map Text (Text, Text)
661+ (errorMap, headUpstream) = flip Map.mapEither headInfo $ \case
665+ putLog Debug $ "branches with upstream branch set: " <> T.pack (show headUpstream)
667+ -- Check that every branch has a remote equivalent
717− when checkClean $ forM_ repoHeads $ \hd -> do
668+ when checkClean $ do
718− [localRev] <- T.lines <$> readGitProcess thunkDir ["rev-parse", T.unpack hd]
669+ let untrackedBranches = Map.keys errorMap
719− forM_ remotes $ \rm -> do
670+ when (not $ L.null untrackedBranches) $ failWith $ T.unlines $
720− --TODO: The error you get if a branch isn't pushed anywhere could be made more user friendly
671+ [ "thunk pack: Certain branches in the thunk have no upstream branch \
721− [remoteMergeRev] <- fmap T.lines $ readGitProcess thunkDir
672+ \set. This means we don't know to check whether all your work is \
722− ["merge-base", T.unpack localRev, "remotes/" <> T.unpack rm <> "/" <> T.unpack hd]
673+ \saved. The offending branches are:"
723− case remoteMergeRev == localRev of
674+ , ""
724− False -> failWith $ mconcat [ "thunk unpack: branch ", hd, " has not been pushed to ", rm ]
675+ , T.unwords untrackedBranches
725− True -> return ()
676+ , ""
726−
677+ , "To fix this, you probably want to do:"
680+ ((\branch -> "git push -u origin " <> branch) <$> untrackedBranches) ++
682+ , "These will push the branches to the default remote under the same \
683+ \name, and (thanks to the `-u`) remember that choice so you don't \
684+ \get this error again."
687+ -- loosely by https://stackoverflow.com/questions/7773939/show-git-ahead-and-behind-info-for-all-branches-including-remotes
688+ stats <- iforM headUpstream $ \branch (upstream, _remote) -> do
689+ (stat :: [Text]) <- T.lines <$> readGitProcess thunkDir
690+ [ "rev-list", "--left-right"
691+ , T.unpack branch <> "..." <> T.unpack upstream
693+ let ahead = length $ [ () | Just ('<', _) <- T.uncons <$> stat ]
694+ behind = length $ [ () | Just ('>', _) <- T.uncons <$> stat ]
695+ pure (upstream, (ahead, behind))
697+ -- Those branches which have commits ahead of, i.e. not on, the upstream
698+ -- branch. Purely being behind is fine.
699+ let nonGood = Map.filter ((/= 0) . fst . snd) stats
701+ when (not $ Map.null nonGood) $ failWith $ T.unlines $
702+ [ "thunk pack: Certain branches in the thunk have commits not yet pushed upstream:"
705+ (flip map (Map.toList nonGood) $ \(branch, (upstream, (ahead, behind))) -> mconcat
706+ [" ", branch, " ahead: ", T.pack (show ahead), " behind: ", T.pack (show behind), " remote branch ", upstream]) ++
708+ , "Please push these upstream and try again. (Or just fetch, if they are somehow \
709+ \pushed but this repo's remote tracking branches don't know it.)"
727− --We assume it's safe to pack the thunk at this point
712+ -- We assume it's safe to pack the thunk at this point
713+ putLog Informational $ "All changes safe in git remotes. OK to pack thunk."
715+ -- Get current branch ``
716+ mCurrentBranch <- listToMaybe
718+ <$> readGitProcess thunkDir ["rev-parse", "--abbrev-ref", "HEAD"]
720+ let remote = maybe "origin" snd $ flip Map.lookup headUpstream =<< mCurrentBranch
728− [remoteUri'] <- fmap T.lines $ readGitProcess thunkDir ["config", "--get", "remote." <> T.unpack upstream <> ".url"]
722+ [remoteUri'] <- fmap T.lines $ readGitProcess thunkDir
725+ , "remote." <> T.unpack remote <> ".url"
728+ remoteUri <- case parseGitUri remoteUri' of
730− let uriParseFailure = "Could not identify git remote: " <> remoteUri'
729+ Nothing -> failWith $ "Could not identify git remote: " <> remoteUri'
731− mRemoteUri = parseGitUri remoteUri'
730+ Just uri -> pure uri
732− case mRemoteUri of
731+ uriThunkPtr remoteUri mCurrentBranch
733− Nothing -> failWith uriParseFailure
732+
734− Just remoteUri -> do
733+-- | Get the latest revision available from the given source
735− refs <- fmap (map (refsToTuples . T.words) . T.lines) $ readGitProcess thunkDir ["show-ref", "--head"]
734+getLatestRev :: MonadObelisk m => ThunkSource -> m ThunkRev
736− -- safe because exactly one hash is associated with HEAD
735+getLatestRev os = do
737− let Just currentHead = fst <$> L.find ((== "HEAD") . snd) refs
736+ let gitS = case os of
738− remoteHeads = Map.fromList $ catMaybes $ fmap
737+ ThunkSource_GitHub s -> forgetGithub False s
739− (\(x,y) -> (,) x <$> T.stripPrefix ("refs/remotes/" <> upstream <> "/") y)
738+ ThunkSource_Git s -> s
740− refs
739+ (_, commit) <- gitGetCommitBranch (_gitSource_url gitS) (untagName <$> _gitSource_branch gitS)
741− localHeads = Map.fromList $ catMaybes $ fmap
740+ case os of
742− (\(x,y) -> (,) x <$> T.stripPrefix "refs/heads/" y)
741+ ThunkSource_GitHub s -> githubThunkRev s commit
743− refs
742+ ThunkSource_Git s -> gitThunkRev s commit
744− currentUpstreamBranch = Map.lookup currentHead remoteHeads
743+
745− <|> Map.lookup currentHead localHeads
744+-- | Convert a URI to a thunk
746− if isGithubThunk remoteUri
745+--
747− then githubThunkPtr remoteUri currentHead currentUpstreamBranch
746+-- If the URL is a github URL, we try to just download an archive for
748− else gitThunkPtr remoteUri currentHead currentUpstreamBranch
747+-- performance. If that doesn't work (e.g. authentication issue), we fall back
749− where
748+-- on just doing things the normal way for git repos in general, and save it as
750− refsToTuples [x, y] = (x, y)
749+-- a regular git thunk.
751− refsToTuples x = error $ "thunk pack: cannot parse ref " <> show x
750+uriThunkPtr :: MonadObelisk m => URI -> Maybe Text -> m ThunkPtr
752− isGithubThunk u
751+uriThunkPtr uri mbranch = do
753− | Just uriAuth <- uriAuthority u
752+ (_, commit) <- gitGetCommitBranch uri mbranch
754− = case uriScheme u of
753+ (src, rev) <- case uriToThunkSource uri mbranch of
755− "ssh:" -> uriAuth == URIAuth "git@" "github.com" ""
754+ ThunkSource_GitHub s -> do
756− s -> s `L.elem` [ "git:", "https:", "http:" ] -- "http:" just redirects to "https:"
755+ rev <- runExceptT $ githubThunkRev s commit
757− && uriRegName uriAuth == "github.com"
756+ case rev of
758− | otherwise = False
757+ Right r -> pure (ThunkSource_GitHub s, r)
759− githubThunkPtr u commit' branch' = do
758+ Left e -> do
760− ["/", owner', repo'] <- return $ splitDirectories (uriPath u)
759+ putLog Warning $ "\
761− let owner = N (T.pack owner')
760+\Failed to fetch archive from GitHub. This is probably a private repo. \
762− dropGitExtension r = fromMaybe r $ T.stripSuffix ".git" r
761+\Falling back on normal fetchgit. Original failure:"
763− repo = N $ dropGitExtension $ T.pack repo'
762+ errorToWarning e
764− commit = N commit'
763+ let s' = forgetGithub True s
765− branch = N <$> branch'
764+ (,) (ThunkSource_Git s') <$> gitThunkRev s' commit
766− mauth <- liftIO $ getHubAuth "github.com"
765+ ThunkSource_Git s -> (,) (ThunkSource_Git s) <$> gitThunkRev s commit
767− repoResult <- liftIO $ executeRequestMaybe mauth $ repositoryR owner repo
766+ pure $ ThunkPtr
768− repoIsPrivate <- either (liftIO . throwIO) (return . repoPrivate) repoResult
767+ { _thunkPtr_rev = rev
769− archiveResult <- liftIO $ executeRequestMaybe mauth $
768+ , _thunkPtr_source = src
770− archiveForR owner repo ArchiveFormatTarball (Just (untagName commit))
769+ }
771− archiveUri <- either (liftIO . throwIO) return archiveResult
770+
772− hash <- getNixSha256ForUriUnpacked archiveUri
771+-- | N.B. Cannot infer all fields.
773− return $ ThunkPtr
772+--
774− { _thunkPtr_rev = ThunkRev
773+-- If the thunk is a GitHub thunk and fails, we do *not* fall back like with
775− { _thunkRev_commit = commitNameToRef commit
774+-- `uriThunkPtr`. Unlike a plain URL, a thunk src explicitly states which method
776− , _thunkRev_nixSha256 = hash
775+-- should be employed, and so we respect that.
777− }
776+uriToThunkSource :: URI -> Maybe Text -> ThunkSource
778− , _thunkPtr_source = ThunkSource_GitHub $ GitHubSource
777+uriToThunkSource u
779− { _gitHubSource_owner = owner
778+ | Right uriAuth <- uriAuthority u
780− , _gitHubSource_repo = repo
779+ , Just scheme <- unRText <$> uriScheme u
781− , _gitHubSource_branch = branch
780+ , case scheme of
782− , _gitHubSource_private = repoIsPrivate
781+ "ssh" -> uriAuth == Authority
783− }
782+ { authUserInfo = Just $ UserInfo (fromRight' $ mkUsername "git") Nothing
784− }
783+ , authHost = fromRight' $ mkHost "github.com"
785− gitThunkPtr u commit branch' = do
784+ , authPort = Nothing
786− let protocols = ["https:", "ssh:", "git:"]
787− unless (T.toLower (T.pack $ uriScheme u) `elem` protocols) $
788− failWith $ "thunk pack: obelisk currently only supports "
789− <> T.intercalate ", " protocols <> " protocols for non-GitHub remotes"
790− hash <- nixPrefetchGit u commit False
791− branch <- case branch' of
792− Nothing -> failWith "thunk pack: git thunks must track a branch"
793− Just b -> pure $ N b
795− { _thunkPtr_rev = ThunkRev
796− { _thunkRev_commit = commitNameToRef (N commit)
797− , _thunkRev_nixSha256 = hash
799− , _thunkPtr_source = ThunkSource_Git $ GitSource
800− { _gitSource_url = u
801− , _gitSource_branch = branch
802− , _gitSource_fetchSubmodules = False -- TODO: How do we determine if this should be true?
786+ s -> s `L.elem` [ "git", "https", "http" ] -- "http:" just redirects to "https:"
787+ && unRText (authHost uriAuth) == "github.com"
788+ , Just (_, owner :| [repoish]) <- uriPath u
789+ = \mbranch -> ThunkSource_GitHub $ GitHubSource
790+ { _gitHubSource_owner = N $ unRText owner
791+ , _gitHubSource_repo = N $ let
792+ repoish' = unRText repoish
793+ in case T.stripSuffix ".git" repoish' of
796+ , _gitHubSource_branch = N <$> mbranch
799+ | otherwise = \mbranch -> ThunkSource_Git $ GitSource
800+ { _gitSource_url = u
801+ , _gitSource_branch = N <$> mbranch
802+ , _gitSource_fetchSubmodules = False -- TODO: How do we determine if this should be true?
805+-- Funny signature indicates no effects depend on the optional branch name.
812+githubThunkRev s commit = do
813+ owner <- forcePP $ _gitHubSource_owner s
814+ repo <- forcePP $ _gitHubSource_repo s
815+ revTarball <- mkPathPiece $ commit <> ".tar.gz"
816+ let archiveUri = URI
817+ { uriScheme = Just $ fromRight' $ mkScheme "https"
818+ , uriAuthority = Right $ Authority
819+ { authUserInfo = Nothing
820+ , authHost = fromRight' $ mkHost "github.com"
821+ , authPort = Nothing
823+ , uriPath = Just ( False
824+ , owner :| [ repo, fromRight' $ mkPathPiece "archive", revTarball ]
827+ , uriFragment = Nothing
829+ hash <- getNixSha256ForUriUnpacked archiveUri
830+ putLog Debug $ "Nix sha256 is " <> hash
832+ { _thunkRev_commit = commitNameToRef $ N commit
833+ , _thunkRev_nixSha256 = hash
836+ forcePP :: Name entity -> m (RText 'PathPiece)
837+ forcePP = mkPathPiece . untagName
844+gitThunkRev s commit = do
845+ let u = _gitSource_url s
846+ protocols = ["https", "ssh", "git"]
847+ Just scheme <- pure $ unRText <$> uriScheme u
848+ unless (T.toLower scheme `elem` protocols) $
849+ failWith $ "obelisk currently only supports "
850+ <> T.intercalate ", " protocols <> " protocols for non-GitHub remotes"
851+ hash <- nixPrefetchGit u commit $ _gitSource_fetchSubmodules s
852+ putLog Informational $ "Nix sha256 is " <> hash
854+ { _thunkRev_commit = commitNameToRef (N commit)
855+ , _thunkRev_nixSha256 = hash
858+-- | Given the URI to a git remote, and an optional branch name, return the name
859+-- of the branch along with the hash of the commit at tip of that branch.
861+-- If the branch name is passed in, it is returned exactly as-is. If it is not
862+-- passed it, the default branch of the repo is used instead.
864+ :: MonadObelisk m => URI -> Maybe Text -> m (Text, CommitId)
865+gitGetCommitBranch uri mbranch = withExitFailMessage ("Failure for git remote " <> uriMsg) $ do
866+ bothMaps <- gitLsRemote
867+ (T.unpack $ render uri)
868+ (GitRef_Branch <$> mbranch)
869+ branch <- case mbranch of
870+ Nothing -> withExitFailMessage "Failed to find default branch" $ do
871+ b <- rethrowE $ gitLookupDefaultBranch bothMaps
872+ putLog Debug $ "Default branch for remote repo " <> uriMsg <> " is " <> b
875+ commit <- rethrowE $ gitLookupCommitForRef bothMaps (GitRef_Branch branch)
876+ putLog Informational $ "Latest commit in branch " <> branch
877+ <> " from remote repo " <> uriMsg
879+ pure (branch, commit)
881+ rethrowE = either failWith pure
806parseGitUri :: Text -> Maybe URI
884parseGitUri :: Text -> Maybe URI
807−parseGitUri x = parseURIReference (T.unpack x) <|> parseSshShorthand x
885+parseGitUri x = parseAbsoluteURI x <|> parseSshShorthand x
887+parseAbsoluteURI :: Text -> Maybe URI
888+parseAbsoluteURI uri = do
889+ parsedUri <- mkURI uri
890+ guard $ isPathAbsolute parsedUri
809parseSshShorthand :: Text -> Maybe URI
893parseSshShorthand :: Text -> Maybe URI
810parseSshShorthand uri = do
894parseSshShorthand uri = do
@@ -819,4 +903,4 @@ parseSshShorthand uri = do
819 -- This check is used to disambiguate a filepath containing a colon from shorthand
903 -- This check is used to disambiguate a filepath containing a colon from shorthand
820 guard $ isNothing (T.findIndex (=='/') authAndHostname)
904 guard $ isNothing (T.findIndex (=='/') authAndHostname)
821 && not (T.null colonAndPath)
905 && not (T.null colonAndPath)
822− parseURI $ T.unpack properUri
906+ mkURI properUri
lib/command/src/Obelisk/Command/Upgrade.hsdeleted−293
@@ -1,293 +0,0 @@
1−{-# LANGUAGE FlexibleContexts #-}
2−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3−{-# LANGUAGE LambdaCase #-}
4−{-# LANGUAGE MultiParamTypeClasses #-}
5−{-# LANGUAGE OverloadedStrings #-}
6−{-# LANGUAGE ScopedTypeVariables #-}
7−{-# LANGUAGE TypeApplications #-}
8−module Obelisk.Command.Upgrade where
10−import Control.Monad (forM, unless, void)
11−import Control.Monad.Catch (onException)
12−import Control.Monad.Except
13−import Control.Monad.IO.Class (liftIO)
14−import Data.Maybe (catMaybes)
15−import Data.Monoid (Any (..), getAny)
16−import Data.Semigroup ((<>))
17−import qualified Data.Set as S
18−import Data.Text (Text)
19−import qualified Data.Text as T
20−import System.Directory
21−import System.FilePath
22−import System.Posix.Process (executeFile)
24−import Obelisk.App (MonadObelisk)
26−import Obelisk.Command.Utils
28−import Obelisk.Command.Project (toImplDir)
29−import Obelisk.Command.Project (findProjectObeliskCommand)
30−import Obelisk.Command.Thunk (ThunkData (..), getThunkGitBranch, readThunk, updateThunk)
32−import Obelisk.Command.Upgrade.Hash
33−import Obelisk.Migration
35−newtype HandOffAction = HandoffAction Any
36− deriving (Monoid, Semigroup, Ord, Eq, Show)
38−instance Action HandOffAction where
39− parseEdgeMeta = HandoffAction . Any . (== "True")
42− = MigrationGraph_ObeliskUpgrade
43− | MigrationGraph_ObeliskHandoff
44− deriving (Eq, Show, Bounded, Enum)
46−graphName :: MigrationGraph -> Text
48− MigrationGraph_ObeliskHandoff -> "obelisk-handoff"
49− MigrationGraph_ObeliskUpgrade -> "obelisk-upgrade"
51−fromGraphName :: Text -> MigrationGraph
53− "obelisk-handoff" -> MigrationGraph_ObeliskHandoff
54− "obelisk-upgrade" -> MigrationGraph_ObeliskUpgrade
55− _ -> error "Invalid graph name specified"
58−graphNames = fmap graphName $ [minBound .. maxBound]
60−ensureCleanProject :: MonadObelisk m => FilePath -> m ()
61−ensureCleanProject project =
62− ensureCleanGitRepo project False "Cannot upgrade with uncommited changes"
64−-- | Decide whether we (ambient ob) should handoff to project obelisk before performing upgrade
65−decideHandOffToProjectOb :: MonadObelisk m => FilePath -> m Bool
66−decideHandOffToProjectOb project = do
67− ensureCleanProject project
68− updateThunk (toImplDir project) $ \projectOb -> do
69− (ambientGraph, ambientHash) <- getAmbientObInfo
70− projectHash <- computeVertexHash projectOb
71− case hasVertex projectHash ambientGraph of
73− putLog Warning "Project ob not found in ambient ob's migration graph; handing off anyway"
75− True -> handleMigrationError (findPathAction ambientGraph projectHash ambientHash) >>= \case
77− putLog Warning "No migration path between project and ambient ob; handing off anyway"
79− Just (HandoffAction dontHandoff) -> do
80− return $ not $ getAny dontHandoff
82− getAmbientObInfo = do
83− ambientOb <- getAmbientOb
84− getMigrationGraph' ambientOb MigrationGraph_ObeliskHandoff >>= \case
86− failWith "Ambient ob has no migration (this can't be possible)"
88− -- We don't have ambient's ob source code, so locate its hash from the
89− -- graph. The last vertex should be it.
90− ambientHash <- handleMigrationError $ getLast (_migration_graph m)
91− return (m, ambientHash)
93−-- | Return the path to the current ('ambient') obelisk process Nix directory
94−getAmbientOb :: MonadObelisk m => m FilePath
95−getAmbientOb = takeDirectory . takeDirectory <$> liftIO getObeliskExe
97−upgradeObelisk :: MonadObelisk m => FilePath -> Maybe Text -> m ()
98−upgradeObelisk project gitBranchM = do
99− ensureCleanProject project
100− gitBranch <- maybe (getObeliskBranch project) pure gitBranchM
101− updateObelisk project gitBranch >>= handOffToNewOb project
103−getObeliskBranch :: MonadObelisk m => FilePath -> m Text
104−getObeliskBranch project = readThunk (toImplDir project) >>= \case
105− Left e -> failWith $ T.pack $ show e
106− Right (ThunkData_Checkout _) -> failWith "obelisk thunk must be packed"
107− Right (ThunkData_Packed tptr) -> case getThunkGitBranch tptr of
110− failWith "You must run `ob upgrade` with the Git branch specified explicitly, as the project's obelisk thunk does not specify any."
112−updateObelisk :: MonadObelisk m => FilePath -> Text -> m Hash
113−updateObelisk project gitBranch =
114− withSpinner ("Fetching new obelisk [" <> gitBranch <> "]") $
115− updateThunk (toImplDir project) $ \obImpl -> do
116− fromHash <- computeVertexHash obImpl
117− callProcessAndLogOutput (Debug, Debug) $
118− gitProc obImpl ["checkout", T.unpack gitBranch]
119− callProcessAndLogOutput (Debug, Debug) $
120− gitProc obImpl ["pull"]
123−handOffToNewOb :: MonadObelisk m => FilePath -> Hash -> m ()
124−handOffToNewOb project fromHash = do
125− impl <- withSpinner' "Preparing for handoff" (Just $ ("Handed off to new obelisk " <>) . T.pack) $
126− findProjectObeliskCommand project >>= \case
127− Nothing -> failWith "Not an obelisk project"
128− Just impl -> pure impl
129− let opts = ["internal", "migrate", T.unpack fromHash]
130− liftIO $ executeFile impl False ("--no-handoff" : opts) Nothing
132−migrateObelisk :: MonadObelisk m => FilePath -> Hash -> m ()
133−migrateObelisk project fromHash = void $ withSpinner' "Migrating to new obelisk" (Just id) $ do
134− updateThunk (toImplDir project) $ \obImpl -> revertObImplOnFail obImpl $ do
135− toHash <- computeVertexHash obImpl
136− g <- getMigrationGraph' obImpl MigrationGraph_ObeliskUpgrade >>= \case
137− Nothing -> failWith "New obelisk has no migration metadata"
140− unless (hasVertex fromHash g) $ do
141− failWith $ "Current obelisk hash " <> fromHash <> " missing in migration graph of new obelisk"
142− unless (hasVertex toHash g) $ do
143− -- This usually means that the target obelisk branch does not have
144− -- migration vertex for its latest commit; typically due to developer
146− failWith $ "New obelisk hash " <> toHash <> " missing in its migration graph"
148− if fromHash == toHash
150− pure $ "No upgrade available (new Obelisk is the same)"
152− putLog Debug $ "Migrating from " <> fromHash <> " to " <> toHash
153− handleMigrationError (findPathAction g fromHash toHash) >>= \case
155− failWith "Unable to find migration path"
157− unless (action == mempty) $ do
158− putLog Notice "To upgrade your project to the new version of obelisk, please follow these instructions:\n"
159− putLog Notice action
160− pure $ "Migrated from " <> fromHash <> " to " <> toHash
162− revertObImplOnFail impl f = f `onException` do
163− putLog Notice $ T.pack $ "Reverting changes to " <> impl
164− callProcessAndLogOutput (Notice, Notice) $ gitProc project ["checkout", impl]
166−-- | Get the migration graph for project
168− :: (Action action, MonadObelisk m)
169− => FilePath -> MigrationGraph -> m (Migration action)
170−getMigrationGraph obDir graph = getMigrationGraph' obDir graph >>= \case
171− Nothing -> failWith "Migration graph missing"
175− :: (Action action, MonadObelisk m)
176− => FilePath -> MigrationGraph -> m (Maybe (Migration action))
177−getMigrationGraph' obDir graph = do
178− let name = graphName graph
179− dir = migrationDir obDir
180− putLog Debug $ "Reading migration graph " <> name <> " from " <> T.pack dir
181− liftIO $ readGraph dir name
183−computeVertexHash :: MonadObelisk m => FilePath -> m Hash
184−computeVertexHash = getDirectoryHash [migrationDirName]
186−-- | Verify the integrity of the migration graph in relation to the Git repo.
187−verifyMigration :: MonadObelisk m => FilePath -> m ()
188−verifyMigration obDir = do
189− upgradeGraph <- withSpinner "Reading migration graph" $
190− getMigrationGraph @Text obDir MigrationGraph_ObeliskUpgrade
191− withSpinner "Checking graph integrity" $
192− handleMigrationError $ ensureGraphIntegrity upgradeGraph
193− headVertex <- liftIO (doesDirectoryExist $ obDir </> ".git") >>= \case
195− withSpinner "Checking existence of HEAD vertex" $
198− hash <- computeVertexHash obDir
199− unless (hasVertex hash upgradeGraph) $
200− failWith $ "No vertex found for obelisk hash " <> hash
202− withSpinner "Checking graph linearity" $
203− -- NOTE: We don't support merge commits (i.e., diamonds in a graph) yet.
204− -- Until we do, ensure that the graph is a fully connected linear list.
205− runExceptT (ensureGraphLinearity upgradeGraph) >>= \case
206− Left (NonLinearGraph_MultipleAdjacents vertex) ->
207− failWith $ "Graph is not linear; branches at vertex: " <> tshow vertex
208− Left (NonLinearGraph_NotConnected isolatedVertices) ->
209− failWith $ "Graph is partly linear, with isolated vertices: " <> tshow isolatedVertices
211− failWith $ "Error in migration graph: " <> tshow e
212− Right lastVertex -> unless (lastVertex == headVertex) $
213− failWith $ "Graph is linear, but its last vertex (" <> lastVertex <> ") is different from head vertex (" <> headVertex <> ")"
215−-- | Create an edge from HEAD vertex to the hash corresponding to the Git
216−-- working copy. The HEAD vertex must already exist.
217−createMigrationEdgeFromHEAD :: MonadObelisk m => FilePath -> m ()
218−createMigrationEdgeFromHEAD obDir = do
219− headHash <- getHeadVertex obDir
220− wcHash <- getDirectoryHash migrationIgnore obDir
221− if (headHash == wcHash)
223− putLog Warning "No migration necessary (working copy has the same hash as that of HEAD)"
225− writeEdge (migrationDir obDir) graphNames headHash wcHash >>= \case
227− putLog Warning "No migration was created"
229− putLog Notice $ "Created edge: " <> T.pack edgeDir
231−-- | Return the hash corresponding to HEAD
233−-- Fail if the hash does not exist in project's migration graph.
234−getHeadVertex :: MonadObelisk m => FilePath -> m Hash
235−getHeadVertex obDir = do
236− projectGraph <- getMigrationGraph @Text obDir MigrationGraph_ObeliskUpgrade
237− [headHash] <- getHashAtGitRevision ["HEAD"] migrationIgnore obDir
238− unless (hasVertex headHash projectGraph) $ do
239− -- This means that the HEAD commit has no vertex in the graph,
240− -- possibly due to developer negligence when commiting it.
241− -- Perhaps we should use a post-commit hook or some such thing
242− -- to reject such commits in the first place? For now, just
244− failWith $ "No vertex found for HEAD (" <> headHash <> ")"
247−-- | Create, or update, the migration graph with new edges and new vertices
248−-- corresponding to every commit in the Git history from HEAD.
250−-- NOTE: This creates a linear graph, and doesn't follow the Git graph
252−backfillGraph :: MonadObelisk m => Maybe Int -> FilePath -> m ()
253−backfillGraph lastN obDir = do
254− revs <- fmap (takeM lastN . fmap (fst . T.breakOn " ") . T.lines) $
255− readProc $ gitProc obDir ["log", "--pretty=oneline"]
256− -- Note: we need to take unique hashes only; this is fine for backfilling.
257− -- But future migrations should ensure that there are no duplicate hashes
258− -- (which would cause cycles) such as those introduced by revert commits.
259− vertices :: [Hash] <- withSpinnerNoTrail "Computing hash for git history" $
260− fmap (unique . reverse) $ getHashAtGitRevision revs [migrationDirName] obDir
262− ("Backfilling with " <> tshow (length vertices) <> " vertices")
263− (Just $ \n -> "Backfilled " <> tshow n <> " edges.") $ do
264− let vertexPairs = zip vertices $ drop 1 vertices
265− let edgesDir = migrationDir obDir
266− liftIO $ createDirectoryIfMissing False edgesDir
267− fmap (length . catMaybes) $ forM vertexPairs $ \(v1, v2) -> do
268− writeEdge edgesDir graphNames v1 v2
270− -- Return unique items in the list /while/ preserving order
271− unique = loop mempty
275− | S.member x s = loop s xs
276− | otherwise = x : loop (S.insert x s) xs
277− takeM n' xs = case n' of
281−handleMigrationError :: MonadObelisk m => Except MigrationError a -> m a
282−handleMigrationError m = case runExcept m of
283− Left e -> failWith $ "Error in migration graph: " <> tshow e
286−migrationDir :: FilePath -> FilePath
287−migrationDir project = project </> migrationDirName
289−migrationIgnore :: [FilePath]
290−migrationIgnore = [migrationDirName]
292−migrationDirName :: FilePath
293−migrationDirName = "migration"
lib/command/src/Obelisk/Command/Upgrade/Hash.hs+1−2
@@ -23,7 +23,6 @@ import System.Process (cwd, proc)
24import Obelisk.App (MonadObelisk)
24import Obelisk.App (MonadObelisk)
25import Obelisk.CliApp
25import Obelisk.CliApp
26−import Obelisk.Command.Nix (withNixRemoteCheck)
27import Obelisk.Command.Utils
26import Obelisk.Command.Utils
29import Obelisk.Migration
28import Obelisk.Migration
@@ -88,7 +87,7 @@ getHashAtGitRevision revs excludes dir = withSystemTempDirectory "obelisk-hashre
88 return result
87 return result
90nixHash :: MonadObelisk m => FilePath -> m Hash
89nixHash :: MonadObelisk m => FilePath -> m Hash
91−nixHash dir = withSpinnerNoTrail "Running `nix-hash`" $ withNixRemoteCheck $
90+nixHash dir = withSpinnerNoTrail "Running `nix-hash`" $
92 readProc $ proc "nix-hash" [dir]
91 readProc $ proc "nix-hash" [dir]
94-- | Clean up the following files in the git working copy
93-- | Clean up the following files in the git working copy
lib/command/src/Obelisk/Command/Utils.hs+103−5
@@ -1,16 +1,30 @@
1{-# LANGUAGE FlexibleContexts #-}
1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE LambdaCase #-}
3+{-# LANGUAGE MultiWayIf #-}
4+{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE OverloadedStrings #-}
5{-# LANGUAGE OverloadedStrings #-}
6+{-# LANGUAGE PatternGuards #-}
4module Obelisk.Command.Utils where
7module Obelisk.Command.Utils where
6−import Control.Applicative (liftA2)
9+import Control.Applicative hiding (many)
10+import Control.Monad.Except
7import Data.Bool (bool)
11import Data.Bool (bool)
12+import qualified Text.Megaparsec.Char.Lexer as ML
8import Data.Semigroup ((<>))
16import Data.Semigroup ((<>))
18+import qualified Data.Map as M
19+import Data.Maybe (maybeToList)
9import Data.Text (Text)
20import Data.Text (Text)
10import qualified Data.Text as T
21import qualified Data.Text as T
22+import Data.Void (Void)
11import System.Directory (canonicalizePath)
23import System.Directory (canonicalizePath)
12import System.Environment (getExecutablePath)
24import System.Environment (getExecutablePath)
13import qualified System.Process as P
25import qualified System.Process as P
26+import Text.Megaparsec as MP
27+import Text.Megaparsec.Char as MP
15import Obelisk.App (MonadObelisk)
29import Obelisk.App (MonadObelisk)
16import Obelisk.CliApp
30import Obelisk.CliApp
@@ -46,9 +60,11 @@ initGit repo = do
46 git ["add", "."]
60 git ["add", "."]
47 git ["commit", "-m", "Initial commit."]
61 git ["commit", "-m", "Initial commit."]
63+gitProcNoRepo :: [String] -> P.CreateProcess
64+gitProcNoRepo = P.proc "git"
49gitProc :: FilePath -> [String] -> P.CreateProcess
66gitProc :: FilePath -> [String] -> P.CreateProcess
50−gitProc repo argsRaw =
67+gitProc repo = gitProcNoRepo . runGitInDir
51− P.proc "git" $ runGitInDir argsRaw
53 runGitInDir args' = case filter (not . null) args' of
69 runGitInDir args' = case filter (not . null) args' of
54 args@("clone":_) -> args <> [repo]
70 args@("clone":_) -> args <> [repo]
@@ -60,7 +76,7 @@ copyDir src dest =
60 (P.proc "cp" ["-a", ".", dest]) { P.cwd = Just src }
76 (P.proc "cp" ["-a", ".", dest]) { P.cwd = Just src }
62readGitProcess :: MonadObelisk m => FilePath -> [String] -> m Text
78readGitProcess :: MonadObelisk m => FilePath -> [String] -> m Text
63−readGitProcess repo = readProcessAndLogStderr Notice . gitProc repo
79+readGitProcess repo = readProcessAndLogOutput (Debug, Notice) . gitProc repo
65processToShellString :: FilePath -> [String] -> String
81processToShellString :: FilePath -> [String] -> String
66processToShellString cmd args = unwords $ map quoteAndEscape (cmd : args)
82processToShellString cmd args = unwords $ map quoteAndEscape (cmd : args)
@@ -76,7 +92,89 @@ runProcSilently = callProcessAndLogOutput (Debug, Debug)
77-- | A simpler wrapper for CliApp's readProcessAndLogStderr with sensible defaults.
93-- | A simpler wrapper for CliApp's readProcessAndLogStderr with sensible defaults.
78readProc :: MonadObelisk m => P.CreateProcess -> m Text
94readProc :: MonadObelisk m => P.CreateProcess -> m Text
79−readProc = readProcessAndLogStderr Error
95+readProc = readProcessAndLogOutput (Debug, Error)
81tshow :: Show a => a -> Text
97tshow :: Show a => a -> Text
82tshow = T.pack . show
98tshow = T.pack . show
100+gitLookupDefaultBranch :: GitLsRemoteMaps -> Either Text Text
101+gitLookupDefaultBranch (refs, _) = do
102+ ref <- case M.lookup GitRef_Head refs of
103+ Just ref -> pure ref
104+ Nothing -> throwError
105+ "No symref entry for HEAD. \
106+ \ Is your git version at least 1.8.5? \
107+ \ Otherwise `git ls-remote --symref` will not work."
109+ GitRef_Branch b -> pure b
111+ "Default ref " <> showGitRef ref <> " is not a branch!"
113+gitLookupCommitForRef :: GitLsRemoteMaps -> GitRef -> Either Text CommitId
114+gitLookupCommitForRef (_, commits) ref = case M.lookup ref commits of
116+ Nothing -> throwError $ "Did not find commit for " <> showGitRef ref
122+ -> m GitLsRemoteMaps
123+gitLsRemote repository mRef = do
124+ t <- readProc $ gitProcNoRepo $
125+ ["ls-remote", "--symref", repository]
126+ ++ (maybeToList $ T.unpack . showGitRef <$> mRef)
127+ maps <- case MP.runParser parseLsRemote "" t of
128+ Left err -> failWith $ T.pack $ MP.parseErrorPretty' t err
129+ Right table -> pure $ bimap M.fromList M.fromList $ partitionEithers $ table
130+ putLog Debug $ "git ls-remote maps: " <> T.pack (show maps)
133+lexeme :: Parsec Void Text a -> Parsec Void Text a
134+lexeme = ML.lexeme $ void $ MP.takeWhileP (Just "within-line white space") $
135+ flip elem [' ', '\t']
137+-- $ git ls-remote --symref git@github.com:obsidiansystems/obelisk.git HEAD
138+-- ref: refs/heads/master HEAD
139+-- d0a8d25dc93f0acd096bc4ff2f550da9e2d0c8f5 refs/heads/master
140+parseLsRemote :: Parsec Void Text [Either (GitRef, GitRef) (GitRef, CommitId)]
142+ many ((fmap Left (try parseRef) <|> fmap Right parseCommit) <* try MP.eol) <* MP.eof
144+ parseRef :: Parsec Void Text (GitRef, GitRef)
145+ parseRef = MP.label "ref and symbolic ref" $ do
147+ ref <- lexeme $ MP.takeWhileP (Just "ref") $ not . isSpace
148+ symbolicRef <- lexeme $ MP.takeWhileP (Just "symbolic ref") $ not . isSpace
149+ return (toGitRef symbolicRef, toGitRef ref)
150+ parseCommit :: Parsec Void Text (GitRef, CommitId)
151+ parseCommit = MP.label "commit and ref" $ do
152+ commitId <- lexeme $ MP.takeWhileP (Just "commit id") $ not . isSpace
153+ ref <- lexeme $ MP.takeWhileP (Just "ref") $ not . isSpace
154+ return (toGitRef ref, commitId)
158+ | GitRef_Branch Text
161+ deriving (Show, Eq, Ord)
163+showGitRef :: GitRef -> Text
165+ GitRef_Head -> "HEAD"
166+ GitRef_Branch x -> "refs/heads/" <> x
167+ GitRef_Tag x -> "refs/tags/" <> x
170+toGitRef :: Text -> GitRef
172+ "HEAD" -> GitRef_Head
174+ | Just s <- "refs/heads/" `T.stripPrefix` r -> GitRef_Branch s
175+ | Just s <- "refs/tags/" `T.stripPrefix` r -> GitRef_Tag s
176+ | otherwise -> GitRef_Other r
180+type GitLsRemoteMaps = (Map GitRef GitRef, Map GitRef CommitId)
lib/command/src/Obelisk/Command/VmBuilder.hs+57−29
@@ -1,13 +1,13 @@
1{-# LANGUAGE FlexibleContexts #-}
1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE QuasiQuotes #-}
3{-# LANGUAGE QuasiQuotes #-}
4+{-# LANGUAGE ScopedTypeVariables #-}
4module Obelisk.Command.VmBuilder where
5module Obelisk.Command.VmBuilder where
6import Control.Applicative (liftA2)
7import Control.Applicative (liftA2)
7−import Control.Monad (unless)
8+import Control.Monad (when, unless)
8−import Control.Monad.Catch (try)
9+import Control.Monad.Catch (handle)
9import Control.Monad.IO.Class (liftIO)
10import Control.Monad.IO.Class (liftIO)
10−import Data.Either (isRight)
11import Data.Monoid ((<>))
11import Data.Monoid ((<>))
12import Data.String (IsString)
12import Data.String (IsString)
13import Data.String.Here.Uninterpolated (hereLit)
13import Data.String.Here.Uninterpolated (hereLit)
@@ -15,23 +15,45 @@ import Data.Text (Text)
15import qualified Data.Text as T
15import qualified Data.Text as T
16import qualified Data.Text.IO as T
16import qualified Data.Text.IO as T
17import System.Directory (createDirectoryIfMissing)
17import System.Directory (createDirectoryIfMissing)
18−import System.Exit (ExitCode)
18+import System.Exit (ExitCode(..))
19import System.FilePath ((<.>), (</>))
19import System.FilePath ((<.>), (</>))
20import qualified System.Info
20import qualified System.Info
21import System.Process (proc)
21import System.Process (proc)
23import Obelisk.App (MonadObelisk, getObeliskUserStateDir)
23import Obelisk.App (MonadObelisk, getObeliskUserStateDir)
24import Obelisk.CliApp
24import Obelisk.CliApp
25−import Obelisk.Command.Nix (withNixRemoteCheck)
27-- | Generate the `--builders` argument string to enable the VM builder after ensuring it is available.
26-- | Generate the `--builders` argument string to enable the VM builder after ensuring it is available.
28getNixBuildersArg :: MonadObelisk m => m String
27getNixBuildersArg :: MonadObelisk m => m String
29getNixBuildersArg = do
28getNixBuildersArg = do
30 stateDir <- liftIO getDockerBuilderStateDir
29 stateDir <- liftIO getDockerBuilderStateDir
30+ let sshIdFile = stateDir </> sshKeyFileName
31+ checkForNixDarwin sshIdFile
31− exists <- containerExists
32+ exists <- containerExists stateDir
32 if exists then startContainer else setupNixDocker stateDir
33 if exists then startContainer else setupNixDocker stateDir
33 pure $ nixBuildersArgString stateDir
34 pure $ nixBuildersArgString stateDir
36+checkForNixDarwin :: MonadObelisk m => String -> m ()
37+checkForNixDarwin sshIdFile = do
38+ (exitCode, _, _) <- readCreateProcessWithExitCode $ proc "which" ["darwin-rebuild"]
39+ unless (exitCode == ExitSuccess) $ failWith $ T.intercalate "\n"
40+ [ "Deployments from macOS require nix-darwin to be installed."
41+ , "Follow the installation instructions here: https://github.com/LnL7/nix-darwin"
42+ , "You'll also need to add the following to your 'configuration.nix' and run 'darwin-rebuild switch':"
44+ , T.intercalate "\n" $ map (" " <>)
45+ [ "nix.distributedBuilds = true;"
46+ , "nix.buildMachines = [{"
47+ , " hostName = " <> T.pack (show (containerName :: String)) <> ";"
48+ , " sshUser = \"root\";"
49+ , " sshKey = " <> T.pack (show sshIdFile) <> ";"
50+ , " sshPort = " <> T.pack (show containerSshPort) <> ";"
51+ , " systems = [ \"x86_64-linux\" ];"
35-- | String to pass to nix's `--builders` arguments to enable the VM builder.
57-- | String to pass to nix's `--builders` arguments to enable the VM builder.
36nixBuildersArgString :: FilePath -> String
58nixBuildersArgString :: FilePath -> String
37nixBuildersArgString stateDir = unwords [containerName, "x86_64-linux", stateDir </> sshKeyFileName, "1", "1", "kvm"]
59nixBuildersArgString stateDir = unwords [containerName, "x86_64-linux", stateDir </> sshKeyFileName, "1", "1", "kvm"]
@@ -41,14 +63,19 @@ containerName :: IsString str => str
41containerName = "obelisk-docker-nix-builder"
63containerName = "obelisk-docker-nix-builder"
43-- | Check to see if the Docker container exists. This will exit with a helpful message if Docker is not installed.
65-- | Check to see if the Docker container exists. This will exit with a helpful message if Docker is not installed.
44−containerExists :: MonadObelisk m => m Bool
66+containerExists :: MonadObelisk m => FilePath -> m Bool
45−containerExists = withExitFailMessage needDockerMsg $ do
67+containerExists stateDir = handle (\(_ :: IOError) -> failWith needDockerMsg) $ do
46 containerNames <- fmap (map T.strip . T.lines) $
68 containerNames <- fmap (map T.strip . T.lines) $
47 readProcessAndLogStderr Error $
69 readProcessAndLogStderr Error $
48 proc "docker" ["container", "list", "--all", "--format", "{{.Names}}"]
70 proc "docker" ["container", "list", "--all", "--format", "{{.Names}}"]
49− pure $ containerName `elem` containerNames
71+ let exists = containerName `elem` containerNames
72+ when exists $ testLinuxBuild stateDir
75+ needDockerMsg = T.intercalate "\n"
51− needDockerMsg = "This feature requires that you have Docker installed and the `docker` command available on your PATH. Please go https://docs.docker.com/ to install Docker and try this command again."
76+ [ "This feature requires that you have Docker installed and the `docker` command available on your PATH."
77+ , "Please go https://docs.docker.com/ to install Docker and try this command again."
53-- | SSH port on localhost that connects to the container.
80-- | SSH port on localhost that connects to the container.
54containerSshPort :: Int
81containerSshPort :: Int
@@ -74,7 +101,7 @@ setupNixDocker stateDir = withSpinner ("Creating Docker container named " <> con
74 proc "ssh-keygen" ["-t", "ed25519", "-f", stateDir </> sshKeyFileName, "-P", ""]
101 proc "ssh-keygen" ["-t", "ed25519", "-f", stateDir </> sshKeyFileName, "-P", ""]
76 -- Build the docker container (which uses the SSH keys in the 'ssh' folder)
103 -- Build the docker container (which uses the SSH keys in the 'ssh' folder)
77− containerId <- readProcessAndLogStderr Error $
104+ containerId <- fmap T.strip $ readProcessAndLogStderr Error $
78 proc "docker" ["build", stateDir, "--quiet"]
105 proc "docker" ["build", stateDir, "--quiet"]
79 callProcessAndLogOutput (Debug, Error) $ proc "docker"
106 callProcessAndLogOutput (Debug, Error) $ proc "docker"
@@ -83,16 +110,11 @@ setupNixDocker stateDir = withSpinner ("Creating Docker container named " <> con
83 , "--publish", show containerSshPort <> ":22"
110 , "--publish", show containerSshPort <> ":22"
84 , "--name", T.unpack containerName, T.unpack containerId
111 , "--name", T.unpack containerName, T.unpack containerId
86− exists <- containerExists
113+ exists <- containerExists stateDir
87 unless exists $
114 unless exists $
88 failWith $ "Expected to see docker container named " <> containerName <> " but it does not exist."
115 failWith $ "Expected to see docker container named " <> containerName <> " but it does not exist."
90− linuxBuildWorked <- if System.Info.os == "linux"
91− then pure False -- The Linux test is useless on Linux so just assume the setup is incomplete.
92− else testLinuxBuild stateDir
117+ testLinuxBuild stateDir
93− unless linuxBuildWorked $ do
94− let sshIdFile = stateDir </> sshKeyFileName
95− failWith $ setupInstructions sshIdFile
97-- | The instructions for setting up SSH access to the container for the Nix daemon.
119-- | The instructions for setting up SSH access to the container for the Nix daemon.
98setupInstructions :: FilePath -> Text
120setupInstructions :: FilePath -> Text
@@ -129,19 +151,24 @@ getDockerBuilderStateDir :: IO FilePath
129getDockerBuilderStateDir = liftA2 (</>) getObeliskUserStateDir (pure "nix-docker-builder")
151getDockerBuilderStateDir = liftA2 (</>) getObeliskUserStateDir (pure "nix-docker-builder")
131-- | Run a test build to see if a Linux build can finish successfully.
153-- | Run a test build to see if a Linux build can finish successfully.
132−testLinuxBuild :: MonadObelisk m => FilePath -> m Bool
154+testLinuxBuild :: MonadObelisk m => FilePath -> m ()
133−testLinuxBuild stateDir =
155+testLinuxBuild stateDir
134− fmap (isRight :: Either ExitCode () -> Bool) $ try $ withNixRemoteCheck $
156+ | System.Info.os == "linux" = failWith "Using the docker builder is not necessary on linux."
135− callProcessAndLogOutput (Debug, Debug) $ proc "nix-build"
157+ | otherwise = do
158+ (exitCode, _stdout, stderr) <- readCreateProcessWithExitCode $ proc "nix-build"
136− [ "-E", "(import <nixpkgs> { system = \"x86_64-linux\"; }).writeText \"test\" builtins.currentTime"
159+ [ "-E", "(import <nixpkgs> { system = \"x86_64-linux\"; }).writeText \"test\" builtins.currentTime"
137− , "--builders", nixBuildersArgString stateDir
160+ , "--builders", nixBuildersArgString stateDir
139−
162+ unless (exitCode == ExitSuccess) $ do
163+ let sshIdFile = stateDir </> sshKeyFileName
164+ putLog Error $ T.pack stderr
165+ failWith $ setupInstructions sshIdFile
140−-- Copied from https://raw.githubusercontent.com/LnL7/nix-docker/bf28b99aebd8e403d2fc2171f4fa8878f857171c/ssh/Dockerfile
167+-- Copied from https://github.com/LnL7/nix-docker/blob/8dcfb3aff1f87cdafeecb0d27964b27c3fb8b1d2/ssh/Dockerfile
141-- Renamed "insecure_rsa" to 'sshKeyFileName'
168-- Renamed "insecure_rsa" to 'sshKeyFileName'
142dockerfile :: Text
169dockerfile :: Text
143dockerfile = [hereLit|
170dockerfile = [hereLit|
144−FROM lnl7/nix:2018-04-17
171+FROM lnl7/nix:2018-09-21
146RUN nix-env -f '<nixpkgs>' -iA \
173RUN nix-env -f '<nixpkgs>' -iA \
@@ -166,7 +193,8 @@ RUN mkdir -p /etc/ssh \
166 ] <> [hereLit|
193 ] <> [hereLit|
169−CMD ["/nix/store/hpnx760s247labqc3nbn2kripk73p0ca-openssh-7.6p1/bin/sshd", "-D", "-e"]
196+CMD ["/nix/store/mydwfxzk8bka4iwjml033dir6gkmqwic-openssh-7.7p1/bin/sshd", "-D", "-e"]
172sshKeyFileName :: FilePath
200sshKeyFileName :: FilePath
lib/frontend/src/Obelisk/Frontend.hs+14−10
@@ -31,6 +31,8 @@ import Data.ByteString (ByteString)
31import Data.Dependent.Sum (DSum (..))
31import Data.Dependent.Sum (DSum (..))
32import Data.Functor.Sum
32import Data.Functor.Sum
33import Data.IORef
33import Data.IORef
34+import Data.Monoid ((<>))
35+import Data.Text (Text)
34import GHCJS.DOM hiding (bracket, catch)
36import GHCJS.DOM hiding (bracket, catch)
35import GHCJS.DOM.Document
37import GHCJS.DOM.Document
36import GHCJS.DOM.Node
38import GHCJS.DOM.Node
@@ -63,6 +65,7 @@ type ObeliskWidget t x route m =
63 , PrimMonad m
65 , PrimMonad m
64 , Prerender x m
66 , Prerender x m
65 , SetRoute t route m
67 , SetRoute t route m
68data Frontend route = Frontend
71data Frontend route = Frontend
@@ -80,7 +83,7 @@ type DomCoreWidget x = PostBuildT DomTimeline (WithJSContextSingleton x (Perform
80--TODO: Rename
83--TODO: Rename
81{-# INLINABLE attachWidget''' #-}
84{-# INLINABLE attachWidget''' #-}
82attachWidget'''
85attachWidget'''
83− :: (EventChannel -> PerformEventT DomTimeline (SpiderHost Global) (IORef (Maybe (EventTrigger DomTimeline ()))))
86+ :: (EventChannel -> PerformEventT DomTimeline DomHost (IORef (Maybe (EventTrigger DomTimeline ()))))
85attachWidget''' w = runDomHost $ do
88attachWidget''' w = runDomHost $ do
86 events <- liftIO newChan
89 events <- liftIO newChan
@@ -142,22 +145,23 @@ runFrontend validFullEncoder frontend = do
142 , MonadFix m
145 , MonadFix m
143 , MonadFix (Performable m)
146 , MonadFix (Performable m)
145− => RoutedT t (R route) (SetRouteT t (R route) m) a
148+ => RoutedT t (R route) (SetRouteT t (R route) (RouteToUrlT (R route) m)) a
147 runMyRouteViewT = runRouteViewT ve
150 runMyRouteViewT = runRouteViewT ve
148 runWithHeadAndBody $ \appendHead appendBody -> runMyRouteViewT $ do
151 runWithHeadAndBody $ \appendHead appendBody -> runMyRouteViewT $ do
149− mapRoutedT (mapSetRouteT appendHead) $ _frontend_head frontend
152+ mapRoutedT (mapSetRouteT (mapRouteToUrlT appendHead)) $ _frontend_head frontend
150− mapRoutedT (mapSetRouteT appendBody) $ _frontend_body frontend
153+ mapRoutedT (mapSetRouteT (mapRouteToUrlT appendBody)) $ _frontend_body frontend
152renderFrontendHtml
155renderFrontendHtml
153− :: (t ~ SpiderTimeline Global)
156+ :: (t ~ DomTimeline)
155− -> RoutedT t r (SetRouteT t r' (PostBuildT Spider (StaticDomBuilderT Spider (PerformEventT Spider (SpiderHost Global))))) ()
159+ -> RoutedT t r (SetRouteT t r' (RouteToUrlT r' (PostBuildT DomTimeline (StaticDomBuilderT DomTimeline (PerformEventT DomTimeline DomHost))))) ()
156− -> RoutedT t r (SetRouteT t r' (PostBuildT Spider (StaticDomBuilderT Spider (PerformEventT Spider (SpiderHost Global))))) ()
160+ -> RoutedT t r (SetRouteT t r' (RouteToUrlT r' (PostBuildT DomTimeline (StaticDomBuilderT DomTimeline (PerformEventT DomTimeline DomHost))))) ()
157 -> IO ByteString
161 -> IO ByteString
158−renderFrontendHtml route headWidget bodyWidget = do
162+renderFrontendHtml urlEnc route headWidget bodyWidget = do
159 --TODO: We should probably have a "NullEventWriterT" or a frozen reflex timeline
163 --TODO: We should probably have a "NullEventWriterT" or a frozen reflex timeline
160− html <- fmap snd $ renderStatic $ fmap fst $ runSetRouteT $ flip runRoutedT (pure route) $
164+ html <- fmap snd $ renderStatic $ fmap fst $ flip runRouteToUrlT urlEnc $ runSetRouteT $ flip runRoutedT (pure route) $
161 el "html" $ do
165 el "html" $ do
162 el "head" headWidget
166 el "head" headWidget
163 el "body" bodyWidget
167 el "body" bodyWidget
lib/migration/obelisk-migration.cabaldeleted−24
@@ -1,24 +0,0 @@
1−name: obelisk-migration
10− algebraic-graphs >= 0.2
24− ghc-options: -Wall -fobject-code
lib/migration/src/Obelisk/Migration.hsdeleted−223
@@ -1,223 +0,0 @@
1−{-# LANGUAGE FlexibleContexts #-}
2−{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE ScopedTypeVariables #-}
5−{-# LANGUAGE TupleSections #-}
6−module Obelisk.Migration where
8−import Control.Monad (forM, forM_, unless, void)
9−import Control.Monad.Except
10−import Control.Monad.IO.Class (MonadIO, liftIO)
11−import Control.Monad.State.Strict (evalStateT, get, put)
13−import qualified Data.Map as Map
14−import Data.Maybe (catMaybes)
15−import Data.Semigroup ((<>))
17−import qualified Data.Set as Set
18−import Data.Text (Text)
19−import qualified Data.Text as T
20−import qualified Data.Text.IO as T
21−import System.Directory
22−import System.FilePath
24−import Algebra.Graph.AdjacencyMap
28−-- Migration graph with edge metadata
29−data Migration action = Migration
30− { _migration_graph :: AdjacencyMap Hash
31− , _migration_actions :: Map (Hash, Hash) action -- Edge metadata
35−-- A path is a list of edges
36−type Path = [(Hash, Hash)]
39− = GraphInternalError Text
41− | MultipleTerminalVertices
43− | NonEquivalentPaths Hash Hash
44− | MissingEdgeInActionMap (Hash, Hash)
45− | NonLinearGraph_MultipleAdjacents Hash
46− | NonLinearGraph_NotConnected (Set Hash)
47− deriving (Eq, Ord, Show)
49−class Action action where
50− parseEdgeMeta :: Text -> action
52−instance Action Text where
55−-- | Get the directed-acylic graph of migration
56−-- TODO: Consider calling getDag only when reading the graph for efficiency.
57−getDag :: (MonadError MigrationError m, Ord a) => AdjacencyMap a -> m (AdjacencyMap a)
58−getDag g = case topSort g of
60− Nothing -> throwError CyclicGraphError
62−-- | Read the graph from a directory of files.
63−readGraph :: Action action => FilePath -> Text -> IO (Maybe (Migration action))
64−readGraph root name = doesDirectoryExist root >>= \case
65− False -> return Nothing
67− allVertexPairs <- listDirectory root >>= return . catMaybes . fmap getEdgeVertices
68− edgesInfo <- fmap catMaybes $ forM allVertexPairs $ \vs -> do
69− getEdgeFor name vs >>= return . fmap (vs, )
70− return $ pure $ Migration (edges $ fmap fst edgesInfo) (Map.fromList edgesInfo)
72− getEdgeVertices p = case T.splitOn "-" $ T.pack p of
73− [v1, v2] -> Just (v1, v2)
75− getEdgeFor graph (v1, v2) = do
76− let f = root </> (T.unpack $ v1 <> "-" <> v2) </> T.unpack graph
77− doesFileExist f >>= \case
79− c <- parseEdgeMeta <$> T.readFile f
84−-- | Ensure that the migration graph is correct
86−-- In a correct migration graph: for all pairs of nodes, all paths between
87−-- those nodes have the same migration value
89−-- Throw the following if integrity check fails
90−-- * `CyclicGraphError`
91−-- * `NonEquivalentPaths`
95− :: (MonadError MigrationError m, Monoid action, Ord action)
96− => Migration action -> m ()
97−ensureGraphIntegrity m = do
98− graph <- fmap adjacencyMap $ getDag $ _migration_graph m
99− firstVertex <- getFirst $ _migration_graph m
101− visitFrom visited acc start = case Map.lookup start graph of
103− Just adjs -> void $ flip traverse (Set.toList adjs) $ \adj -> do
104− acc' <- fmap (mappend acc) $ getAction m (start, adj)
105− visited' <- case Map.lookup adj visited of
106− Nothing -> pure $ Map.insert adj acc' visited
107− Just adjAcc -> if acc' == adjAcc
109− else throwError $ NonEquivalentPaths start adj
110− visitFrom visited' acc' adj
111− -- We only check all paths from the _first_ vertex; it is not necessary to
112− -- check all paths between _all_ pairs of vertices as that can be proved by
113− -- induction, as long as there is exactly one first vertex (which we check on
115− visitFrom mempty mempty firstVertex
117−-- | Ensure that the graph is a fully connected linear list
119−-- Returns the last vertex in the linear list.
120−ensureGraphLinearity :: MonadError MigrationError m => Migration action -> m Hash
121−ensureGraphLinearity m = do
122− graph <- fmap adjacencyMap $ getDag $ _migration_graph m
123− firstVertex <- getFirst $ _migration_graph m
125− allVertices = vertexSet $ _migration_graph m
126− visitFrom start = case Map.lookup start graph of
127− Nothing -> throwError $ GraphInternalError $ "Vertex not found: " <> start
128− Just adjs -> case (Set.toList adjs) of
129− [] -> pure (start, [start])
130− [adj] -> fmap (start :) <$> visitFrom adj
131− _ -> throwError $ NonLinearGraph_MultipleAdjacents start
132− (lastVertex, visitedVertices) <- visitFrom firstVertex
133− let unvisitedVertices = Set.difference allVertices $ Set.fromList visitedVertices
134− if Set.null unvisitedVertices
135− then pure lastVertex
136− else throwError $ NonLinearGraph_NotConnected unvisitedVertices
138−-- | Find the concatenated actions between two vertices
140−-- All paths between the vertices must have the same mappend'ed action;
141−-- otherwise this will throw.
143−-- Complexity: O(V+E)
145− :: (MonadError MigrationError m, Action action, Monoid action, Ord action)
146− => Migration action -> Hash -> Hash -> m (Maybe action)
147−findPathAction m start end = flip evalStateT Map.empty $ do
148− graph <- fmap adjacencyMap $ getDag $ _migration_graph m
150− findPathFromCached start' = do
151− -- TODO: refactor the caching part into a separate `memoize` function
153− case Map.lookup start' cache of
157− result <- findPathFrom start'
158− put $ Map.insert start' result cache
160− findPathFrom start' = if start' == end
163− else case Map.lookup start' graph of
165− actions <- fmap catMaybes $ flip traverse (Set.toList adjs) $ \adj -> do
166− action0 <- getAction m (start', adj)
167− actionM <- findPathFromCached adj
168− pure $ fmap (mappend action0) $ actionM
169− case uniqs actions of
171− [v] -> pure $ Just v -- Exactly one monoidal value; accept.
172− _ -> throwError $ NonEquivalentPaths start' end
175− uniqs = Set.toList . Set.fromList
176− findPathFromCached start
178−hasVertex :: Hash -> Migration action -> Bool
179−hasVertex h (Migration g _) = Set.member h $ vertexSet g
181−-- | Get the action for the given edge (which must exist)
182−getAction :: MonadError MigrationError m => Migration action -> (Hash, Hash) -> m action
183−getAction (Migration _ h) e = case Map.lookup e h of
185− Nothing -> throwError $ MissingEdgeInActionMap e
187−-- | Get the last vertex of the given DAG. Nothing if empty graph.
189−-- Assumes that the graph is fully connected.
190−getLast :: (MonadError MigrationError m, Ord a, Eq a) => AdjacencyMap a -> m a
191−getLast g = lastVertices >>= \case
192− [] -> throwError NoTerminalVertex
194− _ -> throwError MultipleTerminalVertices
199− . filter (\(_, nexts) -> nexts == [])
203−-- | Get the first vertex of the given DAG. Nothing if empty graph.
204−getFirst :: (MonadError MigrationError m, Ord a, Eq a) => AdjacencyMap a -> m a
205−getFirst = getLast . transpose
207−-- | Write an edge directly to the filesystem.
209−-- Actions are written with empty string.
211−-- Return the edge directory created.
212−writeEdge :: MonadIO m => FilePath -> [Text] -> Hash -> Hash -> m (Maybe FilePath)
213−writeEdge dir actionFiles v1 v2 = do
215− fail $ "Cannot create self loop with: " <> T.unpack v1
216− let edgeDir = dir </> (T.unpack $ v1 <> "-" <> v2)
217− liftIO (doesDirectoryExist edgeDir) >>= \case
218− True -> pure Nothing
220− liftIO $ createDirectory edgeDir
221− forM_ actionFiles $ \fp -> liftIO $
222− writeFile (edgeDir </> T.unpack fp) ""
lib/route/src/Obelisk/Route.hs+10−1
@@ -103,6 +103,7 @@ import Data.List.NonEmpty (NonEmpty (..))
103import Data.Map (Map)
103import Data.Map (Map)
104import qualified Data.Map as Map
104import qualified Data.Map as Map
105import Data.Maybe
105import Data.Maybe
106+import Data.Monoid ((<>))
106import Data.Set (Set)
107import Data.Set (Set)
107import qualified Data.Set as Set
108import qualified Data.Set as Set
108import Data.Some (Some)
109import Data.Some (Some)
@@ -528,6 +529,12 @@ unitEncoder expected = unsafeMkEncoder $ EncoderImpl
528singlePathSegmentEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse Text PageName
529singlePathSegmentEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse Text PageName
529singlePathSegmentEncoder = pathOnlyEncoder . singletonListEncoder
530singlePathSegmentEncoder = pathOnlyEncoder . singletonListEncoder
532+pathOnlyEncoderIgnoringQuery :: (Applicative check, MonadError Text parse) => Encoder check parse [Text] PageName
533+pathOnlyEncoderIgnoringQuery = unsafeMkEncoder $ EncoderImpl
534+ { _encoderImpl_decode = \(path, _query) -> pure path
535+ , _encoderImpl_encode = \path -> (path, mempty)
531pathOnlyEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse [Text] PageName
538pathOnlyEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse [Text] PageName
532pathOnlyEncoder = unsafeMkEncoder $ EncoderImpl
539pathOnlyEncoder = unsafeMkEncoder $ EncoderImpl
533 { _encoderImpl_decode = \(path, query) ->
540 { _encoderImpl_decode = \(path, query) ->
@@ -714,6 +721,7 @@ data ResourceRoute :: * -> * where
714 ResourceRoute_Static :: ResourceRoute [Text] -- This [Text] represents the *path in our static files directory*, not necessarily the URL path that the asset gets served at (although that will often be "/static/this/text/thing")
721 ResourceRoute_Static :: ResourceRoute [Text] -- This [Text] represents the *path in our static files directory*, not necessarily the URL path that the asset gets served at (although that will often be "/static/this/text/thing")
715 ResourceRoute_Ghcjs :: ResourceRoute [Text]
722 ResourceRoute_Ghcjs :: ResourceRoute [Text]
716 ResourceRoute_JSaddleWarp :: ResourceRoute (R JSaddleWarpRoute)
723 ResourceRoute_JSaddleWarp :: ResourceRoute (R JSaddleWarpRoute)
724+ ResourceRoute_Version :: ResourceRoute ()
718-- | If there are no additional backend routes in your app (i.e. ObeliskRoute gives you all the routes you need),
726-- | If there are no additional backend routes in your app (i.e. ObeliskRoute gives you all the routes you need),
719-- this constructs a suitable 'Encoder' to use for encoding routes to 'PageName's. If you do have additional backend routes,
727-- this constructs a suitable 'Encoder' to use for encoding routes to 'PageName's. If you do have additional backend routes,
@@ -747,9 +755,10 @@ obeliskRouteSegment r appRouteSegment = case r of
747-- be combined with other such segment encoders before 'pathComponentEncoder' turns it into a proper 'Encoder'.
755-- be combined with other such segment encoders before 'pathComponentEncoder' turns it into a proper 'Encoder'.
748resourceRouteSegment :: (MonadError Text check, MonadError Text parse) => ResourceRoute a -> SegmentResult check parse a
756resourceRouteSegment :: (MonadError Text check, MonadError Text parse) => ResourceRoute a -> SegmentResult check parse a
749resourceRouteSegment = \case
757resourceRouteSegment = \case
750− ResourceRoute_Static -> PathSegment "static" $ pathOnlyEncoder
758+ ResourceRoute_Static -> PathSegment "static" $ pathOnlyEncoderIgnoringQuery
751 ResourceRoute_Ghcjs -> PathSegment "ghcjs" $ pathOnlyEncoder
759 ResourceRoute_Ghcjs -> PathSegment "ghcjs" $ pathOnlyEncoder
752 ResourceRoute_JSaddleWarp -> PathSegment "jsaddle" $ jsaddleWarpRouteEncoder
760 ResourceRoute_JSaddleWarp -> PathSegment "jsaddle" $ jsaddleWarpRouteEncoder
761+ ResourceRoute_Version -> PathSegment "version" $ unitEncoder mempty
754data JSaddleWarpRoute :: * -> * where
763data JSaddleWarpRoute :: * -> * where
755 JSaddleWarpRoute_JavaScript :: JSaddleWarpRoute ()
764 JSaddleWarpRoute_JavaScript :: JSaddleWarpRoute ()
lib/route/src/Obelisk/Route/Frontend.hs+126−5
@@ -41,6 +41,11 @@ module Obelisk.Route.Frontend
41 , SetRoute(..)
41 , SetRoute(..)
42 , runSetRouteT
42 , runSetRouteT
43 , mapSetRouteT
43 , mapSetRouteT
46import Prelude hiding ((.), id)
51import Prelude hiding ((.), id)
@@ -49,7 +54,7 @@ import Obelisk.Route
50import Control.Category (Category (..), (.))
55import Control.Category (Category (..), (.))
51import Control.Category.Cartesian
56import Control.Category.Cartesian
52−import Control.Lens hiding (Bifunctor, bimap, universe)
57+import Control.Lens hiding (Bifunctor, bimap, universe, element)
53import Control.Monad.Fix
58import Control.Monad.Fix
54import Control.Monad.Primitive
59import Control.Monad.Primitive
55import Control.Monad.Ref
60import Control.Monad.Ref
@@ -61,6 +66,8 @@ import Data.Constraint (Dict (..))
61import Data.Dependent.Sum (DSum (..))
66import Data.Dependent.Sum (DSum (..))
62import Data.GADT.Compare
67import Data.GADT.Compare
63import Data.Monoid
68import Data.Monoid
70+import Data.Text (Text)
64import qualified Data.Text as T
71import qualified Data.Text as T
65import Data.Functor.Compose
72import Data.Functor.Compose
66import Reflex.Class
73import Reflex.Class
@@ -95,7 +102,11 @@ instance Monad m => Routed t r (RoutedT t r m) where
95 askRoute = RoutedT ask
102 askRoute = RoutedT ask
97newtype RoutedT t r m a = RoutedT { unRoutedT :: ReaderT (Dynamic t r) m a }
104newtype RoutedT t r m a = RoutedT { unRoutedT :: ReaderT (Dynamic t r) m a }
98− deriving (Functor, Applicative, Monad, MonadFix, MonadTrans, NotReady t, MonadHold t, MonadSample t, PostBuild t, TriggerEvent t, HasJSContext, MonadIO, MonadReflexCreateTrigger t, HasDocument)
105+ deriving (Functor, Applicative, Monad, MonadFix, MonadTrans, NotReady t, MonadHold t, MonadSample t, PostBuild t, TriggerEvent t, MonadIO, MonadReflexCreateTrigger t, HasDocument)
107+instance HasJSContext m => HasJSContext (RoutedT t r m) where
108+ type JSContextPhantom (RoutedT t r m) = JSContextPhantom m
109+ askJSContext = lift askJSContext
100instance Prerender js m => Prerender js (RoutedT t r m) where
111instance Prerender js m => Prerender js (RoutedT t r m) where
101 prerenderClientDict = fmap (\Dict -> Dict) (prerenderClientDict :: Maybe (Dict (PrerenderClientConstraint js m)))
112 prerenderClientDict = fmap (\Dict -> Dict) (prerenderClientDict :: Maybe (Dict (PrerenderClientConstraint js m)))
@@ -213,7 +224,18 @@ strictDynWidget_ f = RoutedT $ ReaderT $ \r -> do
215newtype SetRouteT t r m a = SetRouteT { unSetRouteT :: EventWriterT t (Endo r) m a }
226newtype SetRouteT t r m a = SetRouteT { unSetRouteT :: EventWriterT t (Endo r) m a }
216− deriving (Functor, Applicative, Monad, MonadFix, MonadTrans, NotReady t, MonadHold t, MonadSample t, PostBuild t, TriggerEvent t, HasJSContext, MonadIO, MonadReflexCreateTrigger t, HasDocument, DomBuilder t)
227+ deriving (Functor, Applicative, Monad, MonadFix, MonadTrans, MonadIO, NotReady t, MonadHold t, MonadSample t, PostBuild t, TriggerEvent t, MonadReflexCreateTrigger t, HasDocument)
229+instance (MonadFix m, MonadHold t m, DomBuilder t m) => DomBuilder t (SetRouteT t r m) where
230+ type DomBuilderSpace (SetRouteT t r m) = DomBuilderSpace m
231+ element t cfg child = SetRouteT $ element t cfg $ unSetRouteT child
232+ inputElement = lift . inputElement
233+ textAreaElement = lift . textAreaElement
234+ selectElement cfg child = SetRouteT $ selectElement cfg $ unSetRouteT child
236+instance HasJSContext m => HasJSContext (SetRouteT t r m) where
237+ type JSContextPhantom (SetRouteT t r m) = JSContextPhantom m
238+ askJSContext = lift askJSContext
218mapSetRouteT :: (forall x. m x -> n x) -> SetRouteT t r m a -> SetRouteT t r n a
240mapSetRouteT :: (forall x. m x -> n x) -> SetRouteT t r m a -> SetRouteT t r n a
219mapSetRouteT f (SetRouteT x) = SetRouteT (mapEventWriterT f x)
241mapSetRouteT f (SetRouteT x) = SetRouteT (mapEventWriterT f x)
@@ -275,6 +297,85 @@ instance (Monad m, MonadQuery t vs m) => MonadQuery t vs (SetRouteT t r m) where
275 askQueryResult = lift askQueryResult
297 askQueryResult = lift askQueryResult
276 queryIncremental = lift . queryIncremental
298 queryIncremental = lift . queryIncremental
300+class RouteToUrl r m | m -> r where
301+ askRouteToUrl :: m (r -> Text)
303+newtype RouteToUrlT r m a = RouteToUrlT { unRouteToUrlT :: ReaderT (r -> Text) m a }
304+ deriving (Functor, Applicative, Monad, MonadFix, MonadTrans, NotReady t, MonadHold t, MonadSample t, PostBuild t, TriggerEvent t, MonadIO, MonadReflexCreateTrigger t, HasDocument)
307+ :: RouteToUrlT r m a
310+runRouteToUrlT a = runReaderT (unRouteToUrlT a)
312+mapRouteToUrlT :: (forall x. m x -> n x) -> RouteToUrlT r m a -> RouteToUrlT r n a
313+mapRouteToUrlT f (RouteToUrlT m) = RouteToUrlT $ mapReaderT f m
315+instance Monad m => RouteToUrl r (RouteToUrlT r m) where
316+ askRouteToUrl = RouteToUrlT ask
318+instance (Monad m, RouteToUrl r m) => RouteToUrl r (SetRouteT t r' m) where
319+ askRouteToUrl = lift askRouteToUrl
321+instance (Monad m, RouteToUrl r m) => RouteToUrl r (RoutedT t r' m) where
322+ askRouteToUrl = lift askRouteToUrl
324+instance HasJSContext m => HasJSContext (RouteToUrlT r m) where
325+ type JSContextPhantom (RouteToUrlT r m) = JSContextPhantom m
326+ askJSContext = lift askJSContext
328+instance Prerender js m => Prerender js (RouteToUrlT r m) where
329+ prerenderClientDict = fmap (\Dict -> Dict) (prerenderClientDict :: Maybe (Dict (PrerenderClientConstraint js m)))
331+instance Requester t m => Requester t (RouteToUrlT r m) where
332+ type Request (RouteToUrlT r m) = Request m
333+ type Response (RouteToUrlT r m) = Response m
334+ requesting = RouteToUrlT . requesting
335+ requesting_ = RouteToUrlT . requesting_
337+#ifndef ghcjs_HOST_OS
338+deriving instance MonadJSM m => MonadJSM (RouteToUrlT r m)
341+instance PerformEvent t m => PerformEvent t (RouteToUrlT r m) where
342+ type Performable (RouteToUrlT r m) = Performable m
343+ performEvent = lift . performEvent
344+ performEvent_ = lift . performEvent_
346+instance MonadRef m => MonadRef (RouteToUrlT r m) where
347+ type Ref (RouteToUrlT r m) = Ref m
348+ newRef = lift . newRef
349+ readRef = lift . readRef
350+ writeRef r = lift . writeRef r
352+instance HasJS x m => HasJS x (RouteToUrlT r m) where
353+ type JSX (RouteToUrlT r m) = JSX m
354+ liftJS = lift . liftJS
356+instance MonadTransControl (RouteToUrlT r) where
357+ type StT (RouteToUrlT r) a = StT (ReaderT (r -> Text)) a
358+ liftWith = defaultLiftWith RouteToUrlT unRouteToUrlT
359+ restoreT = defaultRestoreT RouteToUrlT
361+instance PrimMonad m => PrimMonad (RouteToUrlT r m ) where
362+ type PrimState (RouteToUrlT r m) = PrimState m
363+ primitive = lift . primitive
365+instance DomBuilder t m => DomBuilder t (RouteToUrlT r m) where
366+ type DomBuilderSpace (RouteToUrlT r m) = DomBuilderSpace m
368+instance Adjustable t m => Adjustable t (RouteToUrlT r m) where
369+ runWithReplace a0 a' = RouteToUrlT $ runWithReplace (coerce a0) $ coerceEvent a'
370+ traverseIntMapWithKeyWithAdjust f a0 a' = RouteToUrlT $ traverseIntMapWithKeyWithAdjust (coerce f) (coerce a0) $ coerce a'
371+ traverseDMapWithKeyWithAdjust f a0 a' = RouteToUrlT $ traverseDMapWithKeyWithAdjust (\k v -> coerce $ f k v) (coerce a0) $ coerce a'
372+ traverseDMapWithKeyWithAdjustWithMove f a0 a' = RouteToUrlT $ traverseDMapWithKeyWithAdjustWithMove (\k v -> coerce $ f k v) (coerce a0) $ coerce a'
374+instance (Monad m, MonadQuery t vs m) => MonadQuery t vs (RouteToUrlT r m) where
375+ tellQueryIncremental = lift . tellQueryIncremental
376+ askQueryResult = lift askQueryResult
377+ queryIncremental = lift . queryIncremental
278runRouteViewT
379runRouteViewT
279 :: forall t m r a.
380 :: forall t m r a.
280 ( TriggerEvent t m
381 ( TriggerEvent t m
@@ -285,7 +386,7 @@ runRouteViewT
285 , MonadFix m
386 , MonadFix m
287 => (Encoder Identity Identity r PageName)
388 => (Encoder Identity Identity r PageName)
288− -> RoutedT t r (SetRouteT t r m) a
389+ -> RoutedT t r (SetRouteT t r (RouteToUrlT r m)) a
290runRouteViewT routeEncoder a = do
391runRouteViewT routeEncoder a = do
291 rec historyState <- manageHistory $ HistoryCommand_PushState <$> setState
392 rec historyState <- manageHistory $ HistoryCommand_PushState <$> setState
@@ -298,7 +399,7 @@ runRouteViewT routeEncoder a = do
299 errorLeft (Left e) = error (T.unpack e)
400 errorLeft (Left e) = error (T.unpack e)
300 errorLeft (Right x) = x
401 errorLeft (Right x) = x
301− (result, changeState) <- runSetRouteT $ runRoutedT a route
402+ (result, changeState) <- runRouteToUrlT (runSetRouteT $ runRoutedT a route) $ (\(p, q) -> T.pack $ p <> q) . encode theEncoder
302 let f (currentHistoryState, oldRoute) change =
403 let f (currentHistoryState, oldRoute) change =
303 let newRoute = appEndo change oldRoute
404 let newRoute = appEndo change oldRoute
304 (newPath, newQuery) = encode theEncoder newRoute
405 (newPath, newQuery) = encode theEncoder newRoute
@@ -322,6 +423,26 @@ runRouteViewT routeEncoder a = do
322 setState = attachWith f ((,) <$> current historyState <*> current route) changeState
423 setState = attachWith f ((,) <$> current historyState <*> current route) changeState
323 return result
424 return result
426+-- | A link widget that, when clicked, sets the route to the provided route. In non-javascript
427+-- contexts, this widget falls back to using @href@s to control navigation
429+ :: forall t m a route.
431+ , RouteToUrl (R route) m
432+ , SetRoute t (R route) m
434+ => R route -- ^ Target route
435+ -> m a -- ^ Child widget
438+ enc <- askRouteToUrl
439+ let cfg = (def :: ElementConfig EventResult t (DomBuilderSpace m))
440+ & elementConfig_eventSpec %~ addEventSpecFlags (Proxy :: Proxy (DomBuilderSpace m)) Click (\_ -> preventDefault)
441+ & elementConfig_initialAttributes .~ "href" =: enc r
442+ (e, a) <- element "a" cfg w
443+ setRoute $ r <$ domEvent Click e
325-- On ios due to sandboxing when loading the page from a file adapt the
446-- On ios due to sandboxing when loading the page from a file adapt the
326-- path to be based on the hash.
447-- path to be based on the hash.
lib/run/obelisk-run.cabal+1
@@ -22,6 +22,7 @@ library
22 , modern-uri
22 , modern-uri
25+ , obelisk-asset-serve-snap
25 , obelisk-backend
26 , obelisk-backend
26 , obelisk-executable-config
27 , obelisk-executable-config
27 , obelisk-executable-config-inject
28 , obelisk-executable-config-inject
lib/run/src/Obelisk/Run.hs+16−7
@@ -48,11 +48,13 @@ import Network.Wai.Handler.Warp
48import Network.Wai.Handler.Warp.Internal (settingsHost, settingsPort)
48import Network.Wai.Handler.Warp.Internal (settingsHost, settingsPort)
49import Network.WebSockets (ConnectionOptions)
49import Network.WebSockets (ConnectionOptions)
50import Network.WebSockets.Connection (defaultConnectionOptions)
50import Network.WebSockets.Connection (defaultConnectionOptions)
51+import qualified Obelisk.Asset.Serve.Snap as Snap
51import Obelisk.ExecutableConfig (get)
52import Obelisk.ExecutableConfig (get)
52import Obelisk.ExecutableConfig.Inject (injectExecutableConfigs)
53import Obelisk.ExecutableConfig.Inject (injectExecutableConfigs)
53import Obelisk.Frontend
54import Obelisk.Frontend
54import Obelisk.Route.Frontend
55import Obelisk.Route.Frontend
55import Reflex.Dom.Core
56import Reflex.Dom.Core
57+import Snap.Core (Snap)
56import System.Environment
58import System.Environment
57import System.IO
59import System.IO
58import System.Process
60import System.Process
@@ -63,10 +65,11 @@ import Obelisk.Backend
65 :: Int -- ^ Port to run the backend
67 :: Int -- ^ Port to run the backend
68+ -> ([Text] -> Snap ()) -- ^ Static asset handler
66 -> Backend fullRoute frontendRoute -- ^ Backend
69 -> Backend fullRoute frontendRoute -- ^ Backend
67 -> Frontend (R frontendRoute) -- ^ Frontend
70 -> Frontend (R frontendRoute) -- ^ Frontend
69−run port backend frontend = do
72+run port serveStaticAsset backend frontend = do
70 prettifyOutput
73 prettifyOutput
71 let handleBackendErr (e :: IOException) = hPutStrLn stderr $ "backend stopped; make a change to your code to reload - error " <> show e
74 let handleBackendErr (e :: IOException) = hPutStrLn stderr $ "backend stopped; make a change to your code to reload - error " <> show e
72 --TODO: Use Obelisk.Backend.runBackend; this will require separating the checking and running phases
75 --TODO: Use Obelisk.Backend.runBackend; this will require separating the checking and running phases
@@ -79,10 +82,15 @@ run port backend frontend = do
79 getRouteWith validFullEncoder >>= \case
82 getRouteWith validFullEncoder >>= \case
80 Identity r -> case r of
83 Identity r -> case r of
81 InL backendRoute :=> Identity a -> serveRoute $ backendRoute :/ a
84 InL backendRoute :=> Identity a -> serveRoute $ backendRoute :/ a
85+ InR obeliskRoute :=> Identity a ->
82− InR obeliskRoute :=> Identity a -> serveDefaultObeliskApp frontend $ obeliskRoute :/ a
86+ serveDefaultObeliskApp (mkRouteToUrl validFullEncoder) serveStaticAsset frontend $ obeliskRoute :/ a
83 let conf = defRunConfig { _runConfig_redirectPort = port }
87 let conf = defRunConfig { _runConfig_redirectPort = port }
84 runWidget conf frontend validFullEncoder `finally` killThread backendTid
88 runWidget conf frontend validFullEncoder `finally` killThread backendTid
90+-- Convenience wrapper to handle path segments for 'Snap.serveAsset'
91+runServeAsset :: FilePath -> [Text] -> Snap ()
92+runServeAsset rootPath = Snap.serveAsset "" rootPath . T.unpack . T.intercalate "/"
86getConfigRoute :: IO (Maybe URI)
94getConfigRoute :: IO (Maybe URI)
87getConfigRoute = get "config/common/route" >>= \case
95getConfigRoute = get "config/common/route" >>= \case
88 Just r -> case URI.mkURI $ T.strip r of
96 Just r -> case URI.mkURI $ T.strip r of
@@ -135,14 +143,15 @@ obeliskApp opts frontend validFullEncoder uri backend = do
135 { W.pathInfo = fst $ encode jsaddleWarpRouteValidEncoder jsaddleRoute
143 { W.pathInfo = fst $ encode jsaddleWarpRouteValidEncoder jsaddleRoute
137 InR (ObeliskRoute_App appRouteComponent) :=> Identity appRouteRest -> do
145 InR (ObeliskRoute_App appRouteComponent) :=> Identity appRouteRest -> do
138− html <- renderJsaddleFrontend (appRouteComponent :/ appRouteRest) frontend
146+ html <- renderJsaddleFrontend (mkRouteToUrl validFullEncoder) (appRouteComponent :/ appRouteRest) frontend
139− sendResponse $ W.responseLBS H.status200 [("Content-Type", "text/html")] $ BSLC.fromStrict html
147+ sendResponse $ W.responseLBS H.status200 [("Content-Type", staticRenderContentType)] $ BSLC.fromStrict html
140 _ -> backend req sendResponse
148 _ -> backend req sendResponse
142−renderJsaddleFrontend :: route -> Frontend route -> IO ByteString
150+renderJsaddleFrontend :: (route -> Text) -> route -> Frontend route -> IO ByteString
143−renderJsaddleFrontend r f =
151+renderJsaddleFrontend urlEnc r f =
144 let jsaddleScript = elAttr "script" ("src" =: "/jsaddle/jsaddle.js") blank
152 let jsaddleScript = elAttr "script" ("src" =: "/jsaddle/jsaddle.js") blank
153+ jsaddlePreload = elAttr "link" ("rel" =: "preload" <> "as" =: "script" <> "href" =: "/jsaddle/jsaddle.js") blank
145− in renderFrontendHtml r (_frontend_head f >> injectExecutableConfigs) (_frontend_body f >> jsaddleScript)
154+ in renderFrontendHtml urlEnc r (_frontend_head f >> injectExecutableConfigs >> jsaddlePreload) (_frontend_body f >> jsaddleScript)
147-- | like 'bindPortTCP' but reconnects on exception
156-- | like 'bindPortTCP' but reconnects on exception
148bindPortTCPRetry :: Settings
157bindPortTCPRetry :: Settings
lib/selftest/src/Obelisk/SelfTest.hs+74−80
@@ -29,18 +29,17 @@ import System.Info
29import System.IO (Handle, hClose)
29import System.IO (Handle, hClose)
30import System.IO.Temp
30import System.IO.Temp
31import System.Process (readProcessWithExitCode, CreateProcess(cwd), readCreateProcessWithExitCode, proc)
31import System.Process (readProcessWithExitCode, CreateProcess(cwd), readCreateProcessWithExitCode, proc)
33import Test.Hspec
32import Test.Hspec
34import Test.HUnit.Base
33import Test.HUnit.Base
36−import Obelisk.CliApp hiding (runCli)
35+import Obelisk.CliApp hiding (runCli, readCreateProcessWithExitCode)
37import qualified Obelisk.CliApp as CliApp
36import qualified Obelisk.CliApp as CliApp
38import Obelisk.Run (getConfigRoute)
37import Obelisk.Run (getConfigRoute)
40data ObRunState
39data ObRunState
41 = ObRunState_Init
40 = ObRunState_Init
42 | ObRunState_Startup
41 | ObRunState_Startup
43− | ObRunState_BackendStarted Text -- Port of backend
42+ | ObRunState_BackendStarted
44 deriving (Eq, Show)
43 deriving (Eq, Show)
46doubleQuotes :: (IsString a, Semigroup a) => a -> a
45doubleQuotes :: (IsString a, Semigroup a) => a -> a
@@ -65,22 +64,8 @@ tshow :: Show a => a -> Text
65tshow = T.pack . show
64tshow = T.pack . show
67-- | Like `shelly` but used when running `ob` commands
66-- | Like `shelly` but used when running `ob` commands
69−-- This tests the NIX_REMOTE workaround, whether that gets printed
70−-- on failure, and whether retrying with the suggested workaround
71−-- leads to the test succeeding.
72shellyOb :: MonadIO m => (Sh a -> Sh a) -> Sh a -> m a
67shellyOb :: MonadIO m => (Sh a -> Sh a) -> Sh a -> m a
73−shellyOb f obTest = shelly $ f $ do
68+shellyOb f obTest = shelly $ f obTest
74− obTest `catch_sh` \(e :: RunFailed) -> do
75− obStderr <- lastStderr
76− if T.isInfixOf "export NIX_REMOTE" obStderr
79− putLog Notice "Detected NIX_REMOTE suggestion in stderr of failed ob"
80− putLog Warning "Retrying this test with NIX_REMOTE=daemon"
81− setenv "NIX_REMOTE" "daemon"
85main :: IO ()
70main :: IO ()
@@ -91,15 +76,23 @@ main = do
91 let verbosity = bool silently verbosely isVerbose
76 let verbosity = bool silently verbosely isVerbose
92 obeliskImpl <- fromString <$> getEnv "OBELISK_IMPL"
77 obeliskImpl <- fromString <$> getEnv "OBELISK_IMPL"
93 httpManager <- HTTP.newManager HTTP.defaultManagerSettings
78 httpManager <- HTTP.newManager HTTP.defaultManagerSettings
79+ [p0, p1, p2, p3] <- liftIO $ getFreePorts 4
94− withSystemTempDirectory "blank-project" $ \blankProject ->
80+ withSystemTempDirectory "initCache" $ \initCache -> do
81+ -- Setup the ob init cache
82+ void . shellyOb verbosity $ chdir (fromString initCache) $ do
95− hspec $ do
85+ hspec $ parallel $ do
96 let shelly_ = void . shellyOb verbosity
86 let shelly_ = void . shellyOb verbosity
98− inProj :: Sh a -> IO ()
99− inProj = shelly_ . chdir (fromString blankProject)
101 inTmp :: (Shelly.FilePath -> Sh a) -> IO ()
88 inTmp :: (Shelly.FilePath -> Sh a) -> IO ()
102− inTmp f = shelly_ . withSystemTempDirectory "ob-init" $ (chdir <*> f) . fromString
89+ inTmp f = withTmp (chdir <*> f)
91+ withTmp f = shelly_ . withSystemTempDirectory "test" $ f . fromString
93+ inTmpObInit f = inTmp $ \dir -> do
94+ run_ "cp" ["-a", fromString $ initCache <> "/.", toTextIgnore dir]
104 assertRevEQ a b = liftIO . assertEqual "" "" =<< diff a b
97 assertRevEQ a b = liftIO . assertEqual "" "" =<< diff a b
105 assertRevNE a b = liftIO . assertBool "" . (/= "") =<< diff a b
98 assertRevNE a b = liftIO . assertBool "" . (/= "") =<< diff a b
@@ -118,7 +111,7 @@ main = do
119 diff a b = run "git" ["diff", a, b]
112 diff a b = run "git" ["diff", a, b]
121− describe "ob init" $ do
114+ describe "ob init" $ parallel $ do
122 it "works with default impl" $ inTmp $ \_ -> run "ob" ["init"]
115 it "works with default impl" $ inTmp $ \_ -> run "ob" ["init"]
123 it "works with master branch impl" $ inTmp $ \_ -> run "ob" ["init", "--branch", "master"]
116 it "works with master branch impl" $ inTmp $ \_ -> run "ob" ["init", "--branch", "master"]
124 it "works with symlink" $ inTmp $ \_ -> run "ob" ["init", "--symlink", obeliskImpl]
117 it "works with symlink" $ inTmp $ \_ -> run "ob" ["init", "--symlink", obeliskImpl]
@@ -133,57 +126,53 @@ main = do
133 void $ errExit False $ run "ob" ["init", "--symlink", "/dev/null"]
126 void $ errExit False $ run "ob" ["init", "--symlink", "/dev/null"]
134 ls tmp >>= liftIO . assertEqual "" []
127 ls tmp >>= liftIO . assertEqual "" []
136− it "produces a valid route config" $ inTmp $ \tmp -> do
129+ it "produces a valid route config" $ inTmpObInit $ \tmp -> do
138 liftIO $ withCurrentDirectory (T.unpack $ toTextIgnore tmp) $ getConfigRoute `shouldNotReturn` Nothing
130 liftIO $ withCurrentDirectory (T.unpack $ toTextIgnore tmp) $ getConfigRoute `shouldNotReturn` Nothing
132+ -- These tests fail with "Could not find module 'Obelisk.Generated.Static'"
133+ -- when not run by 'nix-build --attr selftest'
140− describe "ob run" $ do
134+ describe "ob run" $ parallel $ do
141− it "works in root directory" $ inTmp $ \_ -> do
135+ it "works in root directory" $ inTmpObInit $ \_ -> do
143− testObRunInDir Nothing httpManager
136+ testObRunInDir p0 p1 Nothing httpManager
144− it "works in sub directory" $ inTmp $ \_ -> do
137+ it "works in sub directory" $ inTmpObInit $ \_ -> do
146− testObRunInDir (Just "frontend") httpManager
138+ testObRunInDir p2 p3 (Just "frontend") httpManager
148 describe "obelisk project" $ parallel $ do
140 describe "obelisk project" $ parallel $ do
149− it "can build obelisk command" $ shelly_ $ run "nix-build" ["-A", "command" , obeliskImpl]
141+ it "can build obelisk command" $ inTmpObInit $ \_ -> run "nix-build" ["-A", "command" , obeliskImpl]
150− it "can build obelisk skeleton" $ shelly_ $ run "nix-build" ["-A", "skeleton", obeliskImpl]
142+ it "can build obelisk skeleton" $ inTmpObInit $ \_ -> run "nix-build" ["-A", "skeleton", obeliskImpl]
151− it "can build obelisk shell" $ shelly_ $ run "nix-build" ["-A", "shell", obeliskImpl]
143+ it "can build obelisk shell" $ inTmpObInit $ \_ -> run "nix-build" ["-A", "shell", obeliskImpl]
152 -- See https://github.com/obsidiansystems/obelisk/issues/101
144 -- See https://github.com/obsidiansystems/obelisk/issues/101
153 -- it "can build everything" $ shelly_ $ run "nix-build" [obeliskImpl]
145 -- it "can build everything" $ shelly_ $ run "nix-build" [obeliskImpl]
155− describe "blank initialized project" $ do
147+ describe "blank initialized project" $ parallel $ do
156− it "can be created" $ inProj $ do
161− it "can build ghc.backend" $ inProj $ do
149+ it "can build ghc.backend" $ inTmpObInit $ \_ -> do
162 run "nix-build" ["--no-out-link", "-A", "ghc.backend"]
150 run "nix-build" ["--no-out-link", "-A", "ghc.backend"]
163− it "can build ghcjs.frontend" $ inProj $ do
151+ it "can build ghcjs.frontend" $ inTmpObInit $ \_ -> do
164 run "nix-build" ["--no-out-link", "-A", "ghcjs.frontend"]
152 run "nix-build" ["--no-out-link", "-A", "ghcjs.frontend"]
166 if os == "darwin"
154 if os == "darwin"
167− then it "can build ios" $ inProj $ run "nix-build" ["--no-out-link", "-A", "ios.frontend" ]
155+ then it "can build ios" $ inTmpObInit $ \_ -> run "nix-build" ["--no-out-link", "-A", "ios.frontend" ]
168− else it "can build android" $ inProj $ run "nix-build" ["--no-out-link", "-A", "android.frontend"]
156+ else it "can build android" $ inTmpObInit $ \_ -> run "nix-build" ["--no-out-link", "-A", "android.frontend"]
170 forM_ ["ghc", "ghcjs"] $ \compiler -> do
158 forM_ ["ghc", "ghcjs"] $ \compiler -> do
172 shell = "shells." <> compiler
160 shell = "shells." <> compiler
173 inShell cmd' = run "nix-shell" ["-A", fromString shell, "--run", cmd']
161 inShell cmd' = run "nix-shell" ["-A", fromString shell, "--run", cmd']
174− it ("can enter " <> shell) $ inProj $ inShell "exit"
162+ it ("can enter " <> shell) $ inTmpObInit $ \_ -> inShell "exit"
175− it ("can build in " <> shell) $ inProj $ inShell $ "cabal new-build --" <> fromString compiler <> " all"
163+ it ("can build in " <> shell) $ inTmpObInit $ \_ -> inShell $ "cabal new-build --" <> fromString compiler <> " all"
177− it "can build reflex project" $ inProj $ do
165+ it "can build reflex project" $ inTmpObInit $ \_ -> do
178 run "nix-build" []
166 run "nix-build" []
180− it "has idempotent thunk update" $ inProj $ do
168+ it "has idempotent thunk update" $ inTmpObInit $ \_ -> do
181 u <- update
169 u <- update
182 uu <- update
170 uu <- update
183 assertRevEQ u uu
171 assertRevEQ u uu
185− describe "ob thunk pack/unpack" $ do
173+ describe "ob thunk pack/unpack" $ parallel $ do
186− it "has thunk pack and unpack inverses" $ inProj $ do
174+ it "has thunk pack and unpack inverses" $ inTmpObInit $ \_ -> do
187 e <- commitAll
176 e <- commitAll
188 eu <- unpack
177 eu <- unpack
189 eup <- pack
178 eup <- pack
@@ -194,6 +183,14 @@ main = do
194 assertRevEQ eu eupu
183 assertRevEQ eu eupu
195 assertRevNE e eu
184 assertRevNE e eu
186+ it "unpacks the correct branch" $ withTmp $ \dir -> do
187+ let branch = "master"
188+ run_ "git" ["clone", "https://github.com/reflex-frp/reflex.git", toTextIgnore dir, "--branch", branch]
189+ run_ "ob" ["thunk", "pack", toTextIgnore dir]
190+ run_ "ob" ["thunk", "unpack", toTextIgnore dir]
191+ branch' <- chdir dir $ run "git" ["rev-parse", "--abbrev-ref", "HEAD"]
192+ liftIO $ assertEqual "" branch (T.strip branch')
197 it "can pack and unpack plain git repos" $ do
194 it "can pack and unpack plain git repos" $ do
198 shelly_ $ withSystemTempDirectory "git-repo" $ \dir -> do
195 shelly_ $ withSystemTempDirectory "git-repo" $ \dir -> do
199 let repo = toTextIgnore $ dir </> ("repo" :: String)
196 let repo = toTextIgnore $ dir </> ("repo" :: String)
@@ -212,23 +209,22 @@ main = do
213 testThunkPack $ fromText repo
210 testThunkPack $ fromText repo
215− it "aborts thunk pack when there are uncommitted files" $ inProj $ do
212+ it "aborts thunk pack when there are uncommitted files" $ inTmpObInit $ \dir -> do
216 void $ unpack
213 void $ unpack
217− testThunkPack (blankProject </> thunk)
214+ testThunkPack (dir </> thunk)
219-- | Run `ob run` in the given directory (maximum of one level deep)
216-- | Run `ob run` in the given directory (maximum of one level deep)
220−testObRunInDir :: Maybe Shelly.FilePath -> HTTP.Manager -> Sh ()
217+testObRunInDir :: Socket.PortNumber -> Socket.PortNumber -> Maybe Shelly.FilePath -> HTTP.Manager -> Sh ()
221−testObRunInDir mdir httpManager = handle_sh (\case ExitSuccess -> pure (); e -> throw e) $ do
218+testObRunInDir p0 p1 mdir httpManager = handle_sh (\case ExitSuccess -> pure (); e -> throw e) $ do
222 let uri p = "http://localhost:" <> T.pack (show p) <> "/" -- trailing slash required for comparison
219 let uri p = "http://localhost:" <> T.pack (show p) <> "/" -- trailing slash required for comparison
223− writefile "config/common/route" . uri =<< liftIO getFreePort -- Use a free port initially
220+ writefile "config/common/route" $ uri p0
224 maybe id chdir mdir $ runHandle "ob" ["run"] $ \stdout -> do
221 maybe id chdir mdir $ runHandle "ob" ["run"] $ \stdout -> do
225− freePort <- liftIO getFreePort
226− (_, firstUri) <- handleObRunStdout httpManager stdout
222+ firstUri <- handleObRunStdout httpManager stdout
227− let newUri = uri freePort
223+ let newUri = uri p1
228 when (firstUri == newUri) $ errorExit $
224 when (firstUri == newUri) $ errorExit $
229 "Startup URI (" <> firstUri <> ") is the same as test URI (" <> newUri <> ")"
225 "Startup URI (" <> firstUri <> ") is the same as test URI (" <> newUri <> ")"
230 maybe id (\_ -> chdir "..") mdir $ alterRouteTo newUri stdout
226 maybe id (\_ -> chdir "..") mdir $ alterRouteTo newUri stdout
231− (_, runningUri) <- handleObRunStdout httpManager stdout
227+ runningUri <- handleObRunStdout httpManager stdout
232 if runningUri /= newUri
228 if runningUri /= newUri
233 then errorExit $ "Reloading failed: expected " <> newUri <> " but got " <> runningUri
229 then errorExit $ "Reloading failed: expected " <> newUri <> " but got " <> runningUri
234 else exit 0
230 else exit 0
@@ -249,7 +245,7 @@ testThunkPack path' = withTempFile (T.unpack $ toTextIgnore path') "test-file" $
249 ensureThunkPackFails "unsaved"
245 ensureThunkPackFails "unsaved"
250 chdir path' $ commit "test commit"
246 chdir path' $ commit "test commit"
251 -- Non-pushed commits in any branch
247 -- Non-pushed commits in any branch
252− ensureThunkPackFails "not been pushed"
248+ ensureThunkPackFails "not yet pushed"
253 -- Uncommitted files (unstaged)
249 -- Uncommitted files (unstaged)
254 liftIO $ T.hPutStrLn handle "test file" >> hClose handle
250 liftIO $ T.hPutStrLn handle "test file" >> hClose handle
255 ensureThunkPackFails "modified"
251 ensureThunkPackFails "modified"
@@ -275,37 +271,35 @@ alterRouteTo uri stdout = do
275 "Reloading failed: " <> T.pack (show t)
271 "Reloading failed: " <> T.pack (show t)
277-- | Handle stdout of `ob run`: check that the frontend and backend servers are started correctly
273-- | Handle stdout of `ob run`: check that the frontend and backend servers are started correctly
278−handleObRunStdout :: HTTP.Manager -> Handle -> Sh (Text, Text)
274+handleObRunStdout :: HTTP.Manager -> Handle -> Sh Text
279−handleObRunStdout httpManager stdout = flip fix ObRunState_Init $ \loop state -> do
275+handleObRunStdout httpManager stdout = flip fix (ObRunState_Init, []) $ \loop (state, msgs) -> do
280 liftIO (T.hGetLine stdout) >>= \t -> case state of
276 liftIO (T.hGetLine stdout) >>= \t -> case state of
281 ObRunState_Init
277 ObRunState_Init
282− | "Running test..." `T.isPrefixOf` t -> loop ObRunState_Startup
278+ | "Running test..." `T.isPrefixOf` t -> loop (ObRunState_BackendStarted, msgs)
283 ObRunState_Startup
279 ObRunState_Startup
284− | t == "backend stopped; make a change to your code to reload" -> loop ObRunState_Startup
280+ | t == "backend stopped; make a change to your code to reload" -> loop (ObRunState_Startup, msgs)
285− | Just port <- "Backend running on port " `T.stripPrefix` t -> loop $ ObRunState_BackendStarted port
281+ -- | Just port <- "Backend running on port " `T.stripPrefix` t -> loop $ ObRunState_BackendStarted port
286 | not (T.null t) -> errorExit $ "Startup: " <> t -- If theres any other output here, startup failed
282 | not (T.null t) -> errorExit $ "Startup: " <> t -- If theres any other output here, startup failed
287− ObRunState_BackendStarted port
283+ ObRunState_BackendStarted
288 | Just uri <- "Frontend running on " `T.stripPrefix` t -> do
284 | Just uri <- "Frontend running on " `T.stripPrefix` t -> do
289− obRunCheck httpManager stdout port uri
285+ obRunCheck httpManager stdout uri
290− pure (port, uri)
286+ pure uri
291 | not (T.null t) -> errorExit $ "Started: " <> t -- If theres any other output here, startup failed
287 | not (T.null t) -> errorExit $ "Started: " <> t -- If theres any other output here, startup failed
288+ _ | "Failed" `T.isPrefixOf` t -> errorExit $ "ob run failed: " <> T.unlines (reverse $ t : msgs)
292− _ -> loop state
289+ | otherwise -> loop (state, t : msgs)
294-- | Make requests to frontend/backend servers to check they are working properly
291-- | Make requests to frontend/backend servers to check they are working properly
295−obRunCheck :: HTTP.Manager -> Handle -> Text -> Text -> Sh ()
292+obRunCheck :: HTTP.Manager -> Handle -> Text -> Sh ()
296−obRunCheck httpManager stdout backendPort frontendUri = do
293+obRunCheck httpManager _stdout frontendUri = do
297 let req uri = liftIO $ HTTP.parseRequest (T.unpack uri) >>= flip HTTP.httpLbs httpManager
294 let req uri = liftIO $ HTTP.parseRequest (T.unpack uri) >>= flip HTTP.httpLbs httpManager
298 req frontendUri >>= \r -> when (HTTP.responseStatus r /= HTTP.ok200) $ errorExit $
295 req frontendUri >>= \r -> when (HTTP.responseStatus r /= HTTP.ok200) $ errorExit $
299 "Request to frontend server failed: " <> T.pack (show r)
296 "Request to frontend server failed: " <> T.pack (show r)
300− void $ req $ "http://localhost:" <> backendPort
301− liftIO (timeout 1000000 $ T.hGetLine stdout) >>= \case
302− Just t | "127.0.0.1" `T.isPrefixOf` t -> pure () -- Backend request logged
303− x -> errorExit $ "Couldn't get backend request log: " <> T.pack (show x)
305−getFreePort :: IO Socket.PortNumber
298+getFreePorts :: Int -> IO [Socket.PortNumber]
299+getFreePorts 0 = pure []
306−getFreePort = Socket.withSocketsDo $ do
300+getFreePorts n = Socket.withSocketsDo $ do
307 addr:_ <- Socket.getAddrInfo (Just Socket.defaultHints) (Just "127.0.0.1") (Just "0")
301 addr:_ <- Socket.getAddrInfo (Just Socket.defaultHints) (Just "127.0.0.1") (Just "0")
308− bracket (open addr) Socket.close Socket.socketPort
302+ bracket (open addr) Socket.close $ \s -> (:) <$> Socket.socketPort s <*> getFreePorts (n - 1)
310 open addr = do
304 open addr = do
311 sock <- Socket.socket (Socket.addrFamily addr) (Socket.addrSocketType addr) (Socket.addrProtocol addr)
305 sock <- Socket.socket (Socket.addrFamily addr) (Socket.addrSocketType addr) (Socket.addrProtocol addr)
lib/snap/obelisk-snap.cabaldeleted−40
@@ -1,40 +0,0 @@
3−Synopsis: Project Synopsis Here
4−Description: Project Description Here
6−Author: Obsidian Systems
7−Maintainer: maintainer@obsidian.systems
8−Stability: Experimental
26− obelisk-asset-serve-snap,
39− other-extensions: TemplateHaskell
40− ghc-options: -threaded -Wall -fno-warn-unused-do-bind -fwarn-tabs -funbox-strict-fields -O2 -fprof-auto-calls -rtsopts
lib/snap/src/Obelisk/Snap.hsdeleted−99
@@ -1,99 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−{-# LANGUAGE QuasiQuotes #-}
3−{-# LANGUAGE OverloadedStrings #-}
5−module Obelisk.Snap where
7−import Obelisk.Asset.Serve.Snap
8−import Obelisk.Snap.Extras
13−import Data.ByteString (ByteString)
16−import qualified Data.Text as T
18−import System.FilePath
19−import Control.Monad.IO.Class
21−-- Data type for web app configuration
23− = AppConfig { _appConfig_initialBody :: m ByteString
24− , _appConfig_initialHead :: ByteString
25− , _appConfig_serveJsexe :: Bool
26− , _appConfig_jsexe :: FilePath
29−-- Default instance for app configuration
30−instance Monad m => Default (AppConfig m) where
31− def = AppConfig { _appConfig_initialBody = return mempty
32− , _appConfig_initialHead = mempty
33− , _appConfig_serveJsexe = True
34− , _appConfig_jsexe = "frontend.jsexe"
37−{- | Takes a location, app, and an app configuration as arguements and
38− routes the request to the correct handler. If "appConfig_serveJsexe"
39− returns "True", additional js paths and asset paths will be appended to
40− handler. Otherwise, it will return "404 Not Found" -}
41−serveAppAt :: MonadSnap m => ByteString -> FilePath -> AppConfig m -> m ()
42−serveAppAt loc app cfg = do
43− route $ [ (loc, ifTop $ serveStaticIndex cfg)
44− , (loc, serveAssets (app </> "static.assets") (app </> "static"))
45− , (loc <> "/version", doNotCache >> serveFileIfExistsAs "text/plain" (app </> "version"))
47− ++ if _appConfig_serveJsexe cfg
48− then [(loc, serveAssets (app </> frontendJsAssetsPath cfg) (app </> frontendJsPath cfg))]
50− ++ [ (loc, doNotCache >> error404) ]
52−-- Helper function used in 'serveAppAt', writes a 404 error message in ByteString
53−error404 :: MonadSnap m => m ()
55− modifyResponse $ setResponseCode 404
56− writeBS "404 Not Found"
58−-- Partially applied 'serveAppAt', specialized to the root directory
59−serveApp :: MonadSnap m => FilePath -> AppConfig m -> m ()
60−serveApp = serveAppAt ""
62−-- Helper function used in 'serveAppAt', returns a frontendJs/... filepath
63−frontendJsPath :: AppConfig m -> FilePath
64−frontendJsPath (AppConfig { _appConfig_jsexe = jsexe }) = "frontendJs" </> jsexe
66−-- Helper function used in 'serveAppAt', returns a frontendJs.assets/... filepath
67−frontendJsAssetsPath :: AppConfig m -> FilePath
68−frontendJsAssetsPath (AppConfig { _appConfig_jsexe = jsexe }) = "frontendJs.assets" </> jsexe
70−-- Helper funtion used in 'serveAppAt', writes a lazy bytestring to the body of Http response
71−serveStaticIndex :: MonadSnap m => AppConfig m -> m ()
72−serveStaticIndex cfg = do
73− -- Decode, pack, and append asset target to file path
74− appJsPath <- liftIO $ getAssetPath (frontendJsAssetsPath cfg) "/all.js"
75− initialBody <- _appConfig_initialBody cfg
76− -- Render and write html head and body to response
77− writeLBS $ renderBS $ doctypehtml_ $ do
79− meta_ [charset_ "utf-8"] -- meta-data charset description
80− meta_ [name_ "viewport", content_ "width=device-width, initial-scale=1.0"] -- meta-data viewport description
81− toHtmlRaw $ _appConfig_initialHead cfg
83− toHtmlRaw initialBody -- HtmlT monad wrapper
84− script_ [type_ "application/javascript", src_ (maybe "/all.js" T.pack appJsPath), defer_ "defer"] ("" :: String)
86−{- | Takes an AppConfig monad and uses it to generate & write Lazy ByteString
87− to the body of the https response. This one comes with hard coded values
89−serveIndex :: MonadSnap m => AppConfig m -> m ()
91− appJsPath <- liftIO $ getAssetPath (frontendJsAssetsPath cfg) "all.js"
92− writeLBS $ renderBS $ doctypehtml_ $ do
94− meta_ [charset_ "utf-8"]
95− meta_ [name_ "viewport", content_ "width=device-width, initial-scale=1.0"]
97− script_ [type_ "application/javascript", src_ (maybe "/all.js" T.pack appJsPath), defer_ "defer"] ("" :: String)
99−makeLenses ''AppConfig
migration/001efbbe866b66eebc6ee1ea0a906f2d-b0c1d039514a686529561f186332c91e/obelisk-handoffdeleted
No changes to the content.
migration/001efbbe866b66eebc6ee1ea0a906f2d-b0c1d039514a686529561f186332c91e/obelisk-upgradedeleted
No changes to the content.
migration/00a480749e96ef7e21fbe8f4943152b1-abdb013baf130e1bd7e7fd04e535c44c/obelisk-handoffdeleted
No changes to the content.
migration/00a480749e96ef7e21fbe8f4943152b1-abdb013baf130e1bd7e7fd04e535c44c/obelisk-upgradedeleted
No changes to the content.
migration/00bee4377690b5040bd5b3702dce2a88-98629a336dcd5fa3524a09f8ea6ad636/obelisk-handoffdeleted
No changes to the content.
migration/00bee4377690b5040bd5b3702dce2a88-98629a336dcd5fa3524a09f8ea6ad636/obelisk-upgradedeleted
No changes to the content.
migration/00c627540326314c7154cc209e8a71e9-67bfa5b784a35e66875fb74ad84a38c0/obelisk-handoffdeleted
No changes to the content.
migration/00c627540326314c7154cc209e8a71e9-67bfa5b784a35e66875fb74ad84a38c0/obelisk-upgradedeleted
No changes to the content.
migration/01c0ee6c93a3f9f69e097c41169927ac-2913c440c7ad7731aae96e60a86bf7a8/obelisk-handoffdeleted
No changes to the content.
migration/01c0ee6c93a3f9f69e097c41169927ac-2913c440c7ad7731aae96e60a86bf7a8/obelisk-upgradedeleted
No changes to the content.
migration/01ddc6354698efa1ae5822da3be562dc-a536d01b9c489f5e00e30abf27427da0/obelisk-handoffdeleted
No changes to the content.
migration/01ddc6354698efa1ae5822da3be562dc-a536d01b9c489f5e00e30abf27427da0/obelisk-upgradedeleted
No changes to the content.
migration/01fb7610e4184ad1b491267fcb0c7f43-c0c1452986b8d4c181bb0c6c83c56a2f/obelisk-handoffdeleted
No changes to the content.
migration/01fb7610e4184ad1b491267fcb0c7f43-c0c1452986b8d4c181bb0c6c83c56a2f/obelisk-upgradedeleted
No changes to the content.
migration/0298e61f6a03e553df08dcef03e27bd1-06d184d1fb27966294a8fee1c7df7cb6/obelisk-handoffdeleted
No changes to the content.
migration/0298e61f6a03e553df08dcef03e27bd1-06d184d1fb27966294a8fee1c7df7cb6/obelisk-upgradedeleted
No changes to the content.
migration/02d0f8b5c7472e6f8a99ec2cfcb59807-5b6770965bbef440db49b0703cd243a3/obelisk-handoffdeleted
No changes to the content.
migration/02d0f8b5c7472e6f8a99ec2cfcb59807-5b6770965bbef440db49b0703cd243a3/obelisk-upgradedeleted
No changes to the content.
migration/02f532fd8bb64a167a5349c2ba8e3331-1088e2464720e12067dd74683546b132/obelisk-handoffdeleted
No changes to the content.
migration/02f532fd8bb64a167a5349c2ba8e3331-1088e2464720e12067dd74683546b132/obelisk-upgradedeleted
No changes to the content.
migration/02fb88dab35884e09deef1721c1cfc13-ae824b83b569b3b23b8e198190371ca0/obelisk-handoffdeleted
No changes to the content.
migration/02fb88dab35884e09deef1721c1cfc13-ae824b83b569b3b23b8e198190371ca0/obelisk-upgradedeleted
No changes to the content.
migration/030ed18dacf3571cbb9e3e7d9d99627b-d37d70fe5d7d11e68b59ce12022281c9/obelisk-handoffdeleted
No changes to the content.
migration/030ed18dacf3571cbb9e3e7d9d99627b-d37d70fe5d7d11e68b59ce12022281c9/obelisk-upgradedeleted
No changes to the content.
migration/03b845f308e73a1567eb843dfca182d2-e9ec84bfe7099b713c0fda32308f5815/obelisk-handoffdeleted
No changes to the content.
migration/03b845f308e73a1567eb843dfca182d2-e9ec84bfe7099b713c0fda32308f5815/obelisk-upgradedeleted
No changes to the content.
migration/03b9747848d7f3e995b118f776ef96c7-3da702ef7f531ad6db874ac3f85e9c06/obelisk-handoffdeleted−1
migration/03b9747848d7f3e995b118f776ef96c7-3da702ef7f531ad6db874ac3f85e9c06/obelisk-upgradedeleted
No changes to the content.
migration/04a5ae41e8fcef5f719cb84d01430382-f391c6a74ee14217ce4565c278fceed6/obelisk-handoffdeleted
No changes to the content.
migration/04a5ae41e8fcef5f719cb84d01430382-f391c6a74ee14217ce4565c278fceed6/obelisk-upgradedeleted
No changes to the content.
migration/04dd95ecb889ac1b0a616ddfeec781c4-f790ac9400501511b4ee045e22bc5fe1/obelisk-handoffdeleted
No changes to the content.
migration/04dd95ecb889ac1b0a616ddfeec781c4-f790ac9400501511b4ee045e22bc5fe1/obelisk-upgradedeleted
No changes to the content.
migration/0535e06dd0d61f3e6970b491a17cf1f8-28a6ada033c86e5ae914cc31cecb6239/obelisk-handoffdeleted
No changes to the content.
migration/0535e06dd0d61f3e6970b491a17cf1f8-28a6ada033c86e5ae914cc31cecb6239/obelisk-upgradedeleted
No changes to the content.
migration/053c0b2f84a7a2eadeb5c3f9575ffa0d-2600ab2ec96d3177d2a6b3462e09862d/obelisk-handoffdeleted
No changes to the content.
migration/053c0b2f84a7a2eadeb5c3f9575ffa0d-2600ab2ec96d3177d2a6b3462e09862d/obelisk-upgradedeleted
No changes to the content.
migration/063665b78b6705e7de952f73fa9797bf-172e629829334d2b33cda8d3b5e0b148/obelisk-handoffdeleted
No changes to the content.
migration/063665b78b6705e7de952f73fa9797bf-172e629829334d2b33cda8d3b5e0b148/obelisk-upgradedeleted
No changes to the content.
migration/06d184d1fb27966294a8fee1c7df7cb6-b1692927da5ed59af72fac5be8094fa2/obelisk-handoffdeleted
No changes to the content.
migration/06d184d1fb27966294a8fee1c7df7cb6-b1692927da5ed59af72fac5be8094fa2/obelisk-upgradedeleted
No changes to the content.
migration/071f5b3326b8886de3eddc927b80eb10-28e25b7a8812869a709579cd34e7bcb4/obelisk-handoffdeleted
No changes to the content.
migration/071f5b3326b8886de3eddc927b80eb10-28e25b7a8812869a709579cd34e7bcb4/obelisk-upgradedeleted
No changes to the content.
migration/07900e6c41ab9a78917f66fcf7e0d9b8-554c459ff2cced3e1b11241ed403890d/obelisk-handoffdeleted
No changes to the content.
migration/07900e6c41ab9a78917f66fcf7e0d9b8-554c459ff2cced3e1b11241ed403890d/obelisk-upgradedeleted
No changes to the content.
migration/07900e6c41ab9a78917f66fcf7e0d9b8-8c84f81d9b09a5e0f028f3c6341ffb36/obelisk-handoffdeleted
No changes to the content.
migration/07900e6c41ab9a78917f66fcf7e0d9b8-8c84f81d9b09a5e0f028f3c6341ffb36/obelisk-upgradedeleted−15
@@ -1,15 +0,0 @@
1−# ob deploy: HTTPs support
3−Obelisk deployments now support HTTPs. You must upgrade the deployment repo
4−associated with the obelisk project as follows:
7−cd /your/project's/deployment/repo
8−echo True > enable_https
9−echo admin@yoursite.com > admin_email
10−echo https://yoursite.com/ > config/common/route
11−git add ... && git commit ...
15−If you do not wish to enable HTTPs, write `False` to `enable_https` instead.
migration/0804ef73b54a4dc7fbde18147f33b4f9-00bee4377690b5040bd5b3702dce2a88/obelisk-handoffdeleted
No changes to the content.
migration/0804ef73b54a4dc7fbde18147f33b4f9-00bee4377690b5040bd5b3702dce2a88/obelisk-upgradedeleted
No changes to the content.
migration/08dbdf23867a8efa680283ad251d3429-f2a9ba4a93c3a04acbee2211bca9e27a/obelisk-handoffdeleted
No changes to the content.
migration/08dbdf23867a8efa680283ad251d3429-f2a9ba4a93c3a04acbee2211bca9e27a/obelisk-upgradedeleted
No changes to the content.
migration/0abd9d31c77be8c9a9e83bf1f73276f6-fc42c5fc24031fc6a8836a10cfb45143/obelisk-handoffdeleted
No changes to the content.
migration/0abd9d31c77be8c9a9e83bf1f73276f6-fc42c5fc24031fc6a8836a10cfb45143/obelisk-upgradedeleted
No changes to the content.
migration/0b2cab546a1526414096980fca85d0d3-99aebbfcac51725464bc59571b7d71b8/obelisk-handoffdeleted
No changes to the content.
migration/0b2cab546a1526414096980fca85d0d3-99aebbfcac51725464bc59571b7d71b8/obelisk-upgradedeleted
No changes to the content.
migration/0c6127453069ad707e34ddfedb67e2f9-7c98ef4a123c1a580d368d14e54961b7/obelisk-handoffdeleted
No changes to the content.
migration/0c6127453069ad707e34ddfedb67e2f9-7c98ef4a123c1a580d368d14e54961b7/obelisk-upgradedeleted
No changes to the content.
migration/0c9826e42d5d4fa9988c7db53722826e-c56de2f95c90def16704f62639246bbc/obelisk-handoffdeleted
No changes to the content.
migration/0c9826e42d5d4fa9988c7db53722826e-c56de2f95c90def16704f62639246bbc/obelisk-upgradedeleted
No changes to the content.
migration/0c991bc3c06801f72df48486ee78e350-58479e482d3828ce44f2c8371ed9135a/obelisk-handoffdeleted
No changes to the content.
migration/0c991bc3c06801f72df48486ee78e350-58479e482d3828ce44f2c8371ed9135a/obelisk-upgradedeleted
No changes to the content.
migration/0d3b4cfe9b4c72b830780a4c44942176-214979923f2d7e6278856493c1978fdc/obelisk-handoffdeleted
No changes to the content.
migration/0d3b4cfe9b4c72b830780a4c44942176-214979923f2d7e6278856493c1978fdc/obelisk-upgradedeleted
No changes to the content.
migration/0da1150f0e9fe57d1fafbb6cabe24fa1-a632452cf9c5956becd1a40512472b43/obelisk-handoffdeleted
No changes to the content.
migration/0da1150f0e9fe57d1fafbb6cabe24fa1-a632452cf9c5956becd1a40512472b43/obelisk-upgradedeleted
No changes to the content.
migration/0e4d0f0f0af0925474b0d772be2b145f-b82e9c3fe22feff4bb3a6be49943fd6c/obelisk-handoffdeleted
No changes to the content.
migration/0e4d0f0f0af0925474b0d772be2b145f-b82e9c3fe22feff4bb3a6be49943fd6c/obelisk-upgradedeleted
No changes to the content.
migration/0ec6f67d94d3913cf3243d813238ec39-0804ef73b54a4dc7fbde18147f33b4f9/obelisk-handoffdeleted
No changes to the content.
migration/0ec6f67d94d3913cf3243d813238ec39-0804ef73b54a4dc7fbde18147f33b4f9/obelisk-upgradedeleted
No changes to the content.
migration/0f78d9d6875933336bbf0c1c8888b73f-d1b3f5f5375558bf91d55c88547784b9/obelisk-handoffdeleted
No changes to the content.
migration/0f78d9d6875933336bbf0c1c8888b73f-d1b3f5f5375558bf91d55c88547784b9/obelisk-upgradedeleted
No changes to the content.
migration/0fb3a912a8aaf5ef6f734a25f0bce7e2-cccf4140dc336263489bcf67c8c58f86/obelisk-handoffdeleted
No changes to the content.
migration/0fb3a912a8aaf5ef6f734a25f0bce7e2-cccf4140dc336263489bcf67c8c58f86/obelisk-upgradedeleted
No changes to the content.
migration/0fba399e046852d4ecf8e1dad831a2f9-6620e6dc5622593e5f671127af9ade05/obelisk-handoffdeleted
No changes to the content.
migration/0fba399e046852d4ecf8e1dad831a2f9-6620e6dc5622593e5f671127af9ade05/obelisk-upgradedeleted
No changes to the content.
migration/0fe60df438daa8a2cca5f2b569e361a5-2e3e85cc59aa31f24f18c027542c0510/obelisk-handoffdeleted
No changes to the content.
migration/0fe60df438daa8a2cca5f2b569e361a5-2e3e85cc59aa31f24f18c027542c0510/obelisk-upgradedeleted
No changes to the content.
migration/1088e2464720e12067dd74683546b132-b2282679f6f63cec89d921c3dd512d1e/obelisk-handoffdeleted
No changes to the content.
migration/1088e2464720e12067dd74683546b132-b2282679f6f63cec89d921c3dd512d1e/obelisk-upgradedeleted
No changes to the content.
migration/11a5917ea91e021f1fa541a2fe158c80-d8adb57b2f2266e128ebb6f6d7e65920/obelisk-handoffdeleted
No changes to the content.
migration/11a5917ea91e021f1fa541a2fe158c80-d8adb57b2f2266e128ebb6f6d7e65920/obelisk-upgradedeleted
No changes to the content.
migration/11f38b38c2d38004bb8a9dbfe2ef3e4a-29d9b8b8ae9698888f3ea90b10ff5e92/obelisk-handoffdeleted
No changes to the content.
migration/11f38b38c2d38004bb8a9dbfe2ef3e4a-29d9b8b8ae9698888f3ea90b10ff5e92/obelisk-upgradedeleted
No changes to the content.
migration/1269155fffe21926f3704d5077e04332-1a97559d049bf85cebb762b7e7b70db1/obelisk-handoffdeleted
No changes to the content.
migration/1269155fffe21926f3704d5077e04332-1a97559d049bf85cebb762b7e7b70db1/obelisk-upgradedeleted
No changes to the content.
migration/12c8a24c34c2d8441f3181d179c2baab-bd6728737dffcc3505d30ada344e2f4b/obelisk-handoffdeleted
No changes to the content.
migration/12c8a24c34c2d8441f3181d179c2baab-bd6728737dffcc3505d30ada344e2f4b/obelisk-upgradedeleted
No changes to the content.
migration/131e1d5cc8163ce9a174a8782be23fe7-e323ce1352e512109f1609276fb509b4/obelisk-handoffdeleted
No changes to the content.
migration/131e1d5cc8163ce9a174a8782be23fe7-e323ce1352e512109f1609276fb509b4/obelisk-upgradedeleted
No changes to the content.
migration/13f6767460e94079cdfa6d5e1df79ecb-c106f9398d5c203a1a296b85c7411bf9/obelisk-handoffdeleted
No changes to the content.
migration/13f6767460e94079cdfa6d5e1df79ecb-c106f9398d5c203a1a296b85c7411bf9/obelisk-upgradedeleted
No changes to the content.
migration/145650b66e83adf5bdb8261593076379-e2be519915794ef130249f2be7640382/obelisk-handoffdeleted
No changes to the content.
migration/145650b66e83adf5bdb8261593076379-e2be519915794ef130249f2be7640382/obelisk-upgradedeleted
No changes to the content.
migration/14840816db4b5cfd5580ae099022604a-aaf979dd0121603a8b48127e1ea47c7d/obelisk-handoffdeleted
No changes to the content.
migration/14840816db4b5cfd5580ae099022604a-aaf979dd0121603a8b48127e1ea47c7d/obelisk-upgradedeleted
No changes to the content.
migration/15f3f3f517b38664131b85da0594522f-9715967793be68dfd8c9a7d631f8d589/obelisk-handoffdeleted
No changes to the content.
migration/15f3f3f517b38664131b85da0594522f-9715967793be68dfd8c9a7d631f8d589/obelisk-upgradedeleted
No changes to the content.
migration/1629d0d70e360df6b2280fac36d21e8a-a825fbb74e8d050a5ce10ec4c62b83f5/obelisk-handoffdeleted
No changes to the content.
migration/1629d0d70e360df6b2280fac36d21e8a-a825fbb74e8d050a5ce10ec4c62b83f5/obelisk-upgradedeleted
No changes to the content.
migration/166c5f8e4a0f1dfd227b075a96237386-a5904e3a899e346fe2fe26314f69c075/obelisk-handoffdeleted
No changes to the content.
migration/166c5f8e4a0f1dfd227b075a96237386-a5904e3a899e346fe2fe26314f69c075/obelisk-upgradedeleted
No changes to the content.
migration/16b24e1a12b93ea83d7656a09d5e3338-8a64ec5f2ee43d69607499f085560857/obelisk-handoffdeleted
No changes to the content.
migration/16b24e1a12b93ea83d7656a09d5e3338-8a64ec5f2ee43d69607499f085560857/obelisk-upgradedeleted
No changes to the content.
migration/17089ea0edc0cf4b6f616936f8a06174-a34d758508a0a5d08bc10e76482c4d11/obelisk-handoffdeleted
No changes to the content.
migration/17089ea0edc0cf4b6f616936f8a06174-a34d758508a0a5d08bc10e76482c4d11/obelisk-upgradedeleted
No changes to the content.
migration/172e629829334d2b33cda8d3b5e0b148-a808a04519bbf2874e41028ded9c180c/obelisk-handoffdeleted
No changes to the content.
migration/172e629829334d2b33cda8d3b5e0b148-a808a04519bbf2874e41028ded9c180c/obelisk-upgradedeleted
No changes to the content.
migration/174fa1072ee767be39b7b01aecea5714-6566f0555737425bae9106d1a4a0a2dd/obelisk-handoffdeleted
No changes to the content.
migration/174fa1072ee767be39b7b01aecea5714-6566f0555737425bae9106d1a4a0a2dd/obelisk-upgradedeleted
No changes to the content.
migration/1859cc62bb2f89f528bb2aa170c36e84-be5a7b436cef0ae35cb074700d5f0d00/obelisk-handoffdeleted
No changes to the content.
migration/1859cc62bb2f89f528bb2aa170c36e84-be5a7b436cef0ae35cb074700d5f0d00/obelisk-upgradedeleted
No changes to the content.
migration/190460dabd2b9773c3fe81902d0c8a62-e7385c9eae2b807a483b73be4295b207/obelisk-handoffdeleted
No changes to the content.
migration/190460dabd2b9773c3fe81902d0c8a62-e7385c9eae2b807a483b73be4295b207/obelisk-upgradedeleted
No changes to the content.
migration/1a08b154ae5f898992128e229090c4d8-4e95e2f8ef50420371b71022c644e25d/obelisk-handoffdeleted
No changes to the content.
migration/1a08b154ae5f898992128e229090c4d8-4e95e2f8ef50420371b71022c644e25d/obelisk-upgradedeleted
No changes to the content.
migration/1a97559d049bf85cebb762b7e7b70db1-5cb98d0250bf5224b94e544a5140a54c/obelisk-handoffdeleted
No changes to the content.
migration/1a97559d049bf85cebb762b7e7b70db1-5cb98d0250bf5224b94e544a5140a54c/obelisk-upgradedeleted
No changes to the content.
migration/1ada2d50d7847a12dbe29df4097b5bdc-11a5917ea91e021f1fa541a2fe158c80/obelisk-handoffdeleted
No changes to the content.
migration/1ada2d50d7847a12dbe29df4097b5bdc-11a5917ea91e021f1fa541a2fe158c80/obelisk-upgradedeleted
No changes to the content.
migration/1b1686b03b41bd840ff46776cec7b33a-31a676fd9e1f69bd07380480ec879da0/obelisk-handoffdeleted
No changes to the content.
migration/1b1686b03b41bd840ff46776cec7b33a-31a676fd9e1f69bd07380480ec879da0/obelisk-upgradedeleted
No changes to the content.
migration/1c1c3f2b4426d5d26377eef08dbccb3c-29abdd56a2dbbf3a2a0715210d441d06/obelisk-handoffdeleted
No changes to the content.
migration/1c1c3f2b4426d5d26377eef08dbccb3c-29abdd56a2dbbf3a2a0715210d441d06/obelisk-upgradedeleted
No changes to the content.
migration/1c2c93819c07f33ad899e39ec6769c3c-909b6b2066cbdc991e6c16455f13637c/obelisk-handoffdeleted
No changes to the content.
migration/1c2c93819c07f33ad899e39ec6769c3c-909b6b2066cbdc991e6c16455f13637c/obelisk-upgradedeleted
No changes to the content.
migration/1c4fc23cbf5653613c6060668e065f37-5b252c24612c2ba868580add9d9c19e3/obelisk-handoffdeleted
No changes to the content.
migration/1c4fc23cbf5653613c6060668e065f37-5b252c24612c2ba868580add9d9c19e3/obelisk-upgradedeleted
No changes to the content.
migration/1c9bdb5c544f2e5432f549653a61dabe-20926beb4c30e2efa819d23e5694645e/obelisk-handoffdeleted
No changes to the content.
migration/1c9bdb5c544f2e5432f549653a61dabe-20926beb4c30e2efa819d23e5694645e/obelisk-upgradedeleted
No changes to the content.
migration/1cc8d98f6f61441570fdde2d697e6e3c-69fafe6ab155ff215b6d9d330f700ba1/obelisk-handoffdeleted
No changes to the content.
migration/1cc8d98f6f61441570fdde2d697e6e3c-69fafe6ab155ff215b6d9d330f700ba1/obelisk-upgradedeleted
No changes to the content.
migration/1d084e187591225f0e8fa6fa824f8863-02f532fd8bb64a167a5349c2ba8e3331/obelisk-handoffdeleted
No changes to the content.
migration/1d084e187591225f0e8fa6fa824f8863-02f532fd8bb64a167a5349c2ba8e3331/obelisk-upgradedeleted
No changes to the content.
migration/1df871cede0758cabe43971d9091279d-0b2cab546a1526414096980fca85d0d3/obelisk-handoffdeleted
No changes to the content.
migration/1df871cede0758cabe43971d9091279d-0b2cab546a1526414096980fca85d0d3/obelisk-upgradedeleted
No changes to the content.
migration/1e36dc8817e2784df36d643b7499092d-ba0ccd5ef6110f6c5133d9d6ea6277f0/obelisk-handoffdeleted
No changes to the content.
migration/1e36dc8817e2784df36d643b7499092d-ba0ccd5ef6110f6c5133d9d6ea6277f0/obelisk-upgradedeleted
No changes to the content.
migration/1e376437f069662df26178e4a7873190-ca5ee8f372ecb07b09283081f0298733/obelisk-handoffdeleted
No changes to the content.
migration/1e376437f069662df26178e4a7873190-ca5ee8f372ecb07b09283081f0298733/obelisk-upgradedeleted
No changes to the content.
migration/1f09fcf196bfe90ed52f113c38ffbfdb-d16784e9a2d93db7f953941e3003fa8c/obelisk-handoffdeleted
No changes to the content.
migration/1f09fcf196bfe90ed52f113c38ffbfdb-d16784e9a2d93db7f953941e3003fa8c/obelisk-upgradedeleted
No changes to the content.
migration/1f5b6e2a19c87d3820b953f942ab4a27-8b098f49e1fd1aa10ca22b9dc312644e/obelisk-handoffdeleted
No changes to the content.
migration/1f5b6e2a19c87d3820b953f942ab4a27-8b098f49e1fd1aa10ca22b9dc312644e/obelisk-upgradedeleted
No changes to the content.
migration/1f7fb90cb1e558f5285b2d19a25a1078-5a98cdb6c195e88beac878a3f311c5b5/obelisk-handoffdeleted
No changes to the content.
migration/1f7fb90cb1e558f5285b2d19a25a1078-5a98cdb6c195e88beac878a3f311c5b5/obelisk-upgradedeleted
No changes to the content.
migration/1fe00204f9d2cd653ff2894eae3d9356-4b3f45ce8aeb17ef18d1d9502b74bb7e/obelisk-handoffdeleted
No changes to the content.
migration/1fe00204f9d2cd653ff2894eae3d9356-4b3f45ce8aeb17ef18d1d9502b74bb7e/obelisk-upgradedeleted
No changes to the content.
migration/20926beb4c30e2efa819d23e5694645e-212ead9571b83b8164b3f18d2537d52b/obelisk-handoffdeleted
No changes to the content.
migration/20926beb4c30e2efa819d23e5694645e-212ead9571b83b8164b3f18d2537d52b/obelisk-upgradedeleted
No changes to the content.
migration/212ead9571b83b8164b3f18d2537d52b-3bf8e28473fb05791c5790f8906e2609/obelisk-handoffdeleted
No changes to the content.
migration/212ead9571b83b8164b3f18d2537d52b-3bf8e28473fb05791c5790f8906e2609/obelisk-upgradedeleted
No changes to the content.
migration/214979923f2d7e6278856493c1978fdc-13f6767460e94079cdfa6d5e1df79ecb/obelisk-handoffdeleted
No changes to the content.
migration/214979923f2d7e6278856493c1978fdc-13f6767460e94079cdfa6d5e1df79ecb/obelisk-upgradedeleted
No changes to the content.
migration/215b6810b09f219a5cb3842aacc88432-2ef4f9cce6d15ae62d5112d3c224eb7a/obelisk-handoffdeleted
No changes to the content.
migration/215b6810b09f219a5cb3842aacc88432-2ef4f9cce6d15ae62d5112d3c224eb7a/obelisk-upgradedeleted
No changes to the content.
migration/2164344be67da5d0e57052c15f30646d-0c9826e42d5d4fa9988c7db53722826e/obelisk-handoffdeleted
No changes to the content.
migration/2164344be67da5d0e57052c15f30646d-0c9826e42d5d4fa9988c7db53722826e/obelisk-upgradedeleted
No changes to the content.
migration/237aeb7eee0ffed230234ee04e49569f-55cf43fb0d3868040c9efbf2f92d538a/obelisk-handoffdeleted
No changes to the content.
migration/237aeb7eee0ffed230234ee04e49569f-55cf43fb0d3868040c9efbf2f92d538a/obelisk-upgradedeleted
No changes to the content.
migration/23af4d9671962484de53f537a0626d83-7ce32302cfbba8b7567a05144057f8a3/obelisk-handoffdeleted
No changes to the content.
migration/23af4d9671962484de53f537a0626d83-7ce32302cfbba8b7567a05144057f8a3/obelisk-upgradedeleted
No changes to the content.
migration/24e0d027f4160a6478c1356e51f419cf-4e3e6e8b9d0f4194842e530438ff686f/obelisk-handoffdeleted
No changes to the content.
migration/24e0d027f4160a6478c1356e51f419cf-4e3e6e8b9d0f4194842e530438ff686f/obelisk-upgradedeleted
No changes to the content.
migration/24f151a674662ac47845237d7a9f6a4f-4fe321cf196b9cd25210c35e09e09d8f/obelisk-handoffdeleted
No changes to the content.
migration/24f151a674662ac47845237d7a9f6a4f-4fe321cf196b9cd25210c35e09e09d8f/obelisk-upgradedeleted
No changes to the content.
migration/2543866165016a449562ea7a1ee36f6f-1a08b154ae5f898992128e229090c4d8/obelisk-handoffdeleted
No changes to the content.
migration/2543866165016a449562ea7a1ee36f6f-1a08b154ae5f898992128e229090c4d8/obelisk-upgradedeleted
No changes to the content.
migration/25615a274650370633e8083ed19fbdd0-80cb6b08443d55bb512e4a35b4768b72/obelisk-handoffdeleted
No changes to the content.
migration/25615a274650370633e8083ed19fbdd0-80cb6b08443d55bb512e4a35b4768b72/obelisk-upgradedeleted
No changes to the content.
migration/2600ab2ec96d3177d2a6b3462e09862d-e2b2d878b0ba6eb653b194523bf0a0e0/obelisk-handoffdeleted
No changes to the content.
migration/2600ab2ec96d3177d2a6b3462e09862d-e2b2d878b0ba6eb653b194523bf0a0e0/obelisk-upgradedeleted
No changes to the content.
migration/2619464637b85cb35376393fe612ddae-a8ebe201ab7a7b0211de41b14a95192e/obelisk-handoffdeleted
No changes to the content.
migration/2619464637b85cb35376393fe612ddae-a8ebe201ab7a7b0211de41b14a95192e/obelisk-upgradedeleted
No changes to the content.
migration/26a2491fc8a9658751c1511c777a67bd-470df6504156dc940b8e7f89c148e619/obelisk-handoffdeleted
No changes to the content.
migration/26a2491fc8a9658751c1511c777a67bd-470df6504156dc940b8e7f89c148e619/obelisk-upgradedeleted
No changes to the content.
migration/270b3b3f7bc510c692e3253a895f122a-c2d4eeb20f2b319a2d9dc5b6b0762f83/obelisk-handoffdeleted
No changes to the content.
migration/270b3b3f7bc510c692e3253a895f122a-c2d4eeb20f2b319a2d9dc5b6b0762f83/obelisk-upgradedeleted
No changes to the content.
migration/2773d4a82ca59b48faf036755e163a5f-71c6959cf98e05d356ff798ada6db2b8/obelisk-handoffdeleted
No changes to the content.
migration/2773d4a82ca59b48faf036755e163a5f-71c6959cf98e05d356ff798ada6db2b8/obelisk-upgradedeleted
No changes to the content.
migration/28a6ada033c86e5ae914cc31cecb6239-90b4e20464e08ade5f215f2a4ea28cc6/obelisk-handoffdeleted
No changes to the content.
migration/28a6ada033c86e5ae914cc31cecb6239-90b4e20464e08ade5f215f2a4ea28cc6/obelisk-upgradedeleted
No changes to the content.
migration/28c5fec3b7b0b14b3625d5c8f60bcf68-4509e2a908da9e497fa67acacdd107b6/obelisk-handoffdeleted
No changes to the content.
migration/28c5fec3b7b0b14b3625d5c8f60bcf68-4509e2a908da9e497fa67acacdd107b6/obelisk-upgradedeleted
No changes to the content.
migration/28e25b7a8812869a709579cd34e7bcb4-2543866165016a449562ea7a1ee36f6f/obelisk-handoffdeleted
No changes to the content.
migration/28e25b7a8812869a709579cd34e7bcb4-2543866165016a449562ea7a1ee36f6f/obelisk-upgradedeleted
No changes to the content.
migration/2913c440c7ad7731aae96e60a86bf7a8-a08aebb6f40fb45d174b229532314ac4/obelisk-handoffdeleted
No changes to the content.
migration/2913c440c7ad7731aae96e60a86bf7a8-a08aebb6f40fb45d174b229532314ac4/obelisk-upgradedeleted
No changes to the content.
migration/29abdd56a2dbbf3a2a0715210d441d06-51c7d001730ddd3d76e0c8bb57038773/obelisk-handoffdeleted
No changes to the content.
migration/29abdd56a2dbbf3a2a0715210d441d06-51c7d001730ddd3d76e0c8bb57038773/obelisk-upgradedeleted
No changes to the content.
migration/29d9b8b8ae9698888f3ea90b10ff5e92-1ada2d50d7847a12dbe29df4097b5bdc/obelisk-handoffdeleted
No changes to the content.
migration/29d9b8b8ae9698888f3ea90b10ff5e92-1ada2d50d7847a12dbe29df4097b5bdc/obelisk-upgradedeleted
No changes to the content.
migration/29fd07af89cc31526fca00226ff52a82-50b85e79010ad50ee275eaeba0df6f8d/obelisk-handoffdeleted
No changes to the content.
migration/29fd07af89cc31526fca00226ff52a82-50b85e79010ad50ee275eaeba0df6f8d/obelisk-upgradedeleted
No changes to the content.
migration/2ba356b187db8db13b8aa40f43ca025f-3c1fc501da00f467c9a48a1ddee2c2b0/obelisk-handoffdeleted
No changes to the content.
migration/2ba356b187db8db13b8aa40f43ca025f-3c1fc501da00f467c9a48a1ddee2c2b0/obelisk-upgradedeleted
No changes to the content.
migration/2bdd4221307cafa3e98c4d3017cdc912-5f6fe243beb9fcc0c4117536022fc14c/obelisk-handoffdeleted
No changes to the content.
migration/2bdd4221307cafa3e98c4d3017cdc912-5f6fe243beb9fcc0c4117536022fc14c/obelisk-upgradedeleted
No changes to the content.
migration/2c1521e5a5be64e6d28a9fdae950cd76-92ab733e8991f12cc12148f8d4e1b35d/obelisk-handoffdeleted
No changes to the content.
migration/2c1521e5a5be64e6d28a9fdae950cd76-92ab733e8991f12cc12148f8d4e1b35d/obelisk-upgradedeleted
No changes to the content.
migration/2ccf977797628dc3b1c002927fedc7a8-46f9c6c66e2bd8980402b6117ca40965/obelisk-handoffdeleted
No changes to the content.
migration/2ccf977797628dc3b1c002927fedc7a8-46f9c6c66e2bd8980402b6117ca40965/obelisk-upgradedeleted
No changes to the content.
migration/2df092178e167b474dd08dfa46ec3a49-9c94cd459a25b5c2de56067c8fdac620/obelisk-handoffdeleted
No changes to the content.
migration/2df092178e167b474dd08dfa46ec3a49-9c94cd459a25b5c2de56067c8fdac620/obelisk-upgradedeleted
No changes to the content.
migration/2e3e85cc59aa31f24f18c027542c0510-47357c6c23f049241902bf2e2e686ac8/obelisk-handoffdeleted
No changes to the content.
migration/2e3e85cc59aa31f24f18c027542c0510-47357c6c23f049241902bf2e2e686ac8/obelisk-upgradedeleted
No changes to the content.
migration/2e7cdc2bea08bb2358219ddefef372e0-a00870cfca85ff8dae5db3a78f5a227d/obelisk-handoffdeleted
No changes to the content.
migration/2e7cdc2bea08bb2358219ddefef372e0-a00870cfca85ff8dae5db3a78f5a227d/obelisk-upgradedeleted
No changes to the content.
migration/2e9a04a228106f62128ea5bd19d6b25e-947784563e3a27cf6486bed9a3c52f15/obelisk-handoffdeleted
No changes to the content.
migration/2e9a04a228106f62128ea5bd19d6b25e-947784563e3a27cf6486bed9a3c52f15/obelisk-upgradedeleted
No changes to the content.
migration/2eb907820012f77e60350430d89631fe-494be5819cd601fd2f0c20e1b23b84a3/obelisk-handoffdeleted
No changes to the content.
migration/2eb907820012f77e60350430d89631fe-494be5819cd601fd2f0c20e1b23b84a3/obelisk-upgradedeleted
No changes to the content.
migration/2ef4f9cce6d15ae62d5112d3c224eb7a-a080b8549e32f21fec11084f4ab1e052/obelisk-handoffdeleted
No changes to the content.
migration/2ef4f9cce6d15ae62d5112d3c224eb7a-a080b8549e32f21fec11084f4ab1e052/obelisk-upgradedeleted
No changes to the content.
migration/2f3ecb5cdb0ab839a49271d91dd7852a-f9ad863c0bebc103f8b81afdf82e6293/obelisk-handoffdeleted
No changes to the content.
migration/2f3ecb5cdb0ab839a49271d91dd7852a-f9ad863c0bebc103f8b81afdf82e6293/obelisk-upgradedeleted
No changes to the content.
migration/2f928f9c4a137186f808a231c9e3c141-9e61f37dd79310b71c80ee166aeb4e80/obelisk-handoffdeleted
No changes to the content.
migration/2f928f9c4a137186f808a231c9e3c141-9e61f37dd79310b71c80ee166aeb4e80/obelisk-upgradedeleted
No changes to the content.
migration/315cd79f97dae2f3669551dc03e0fd27-c801cbcf925c0a7b084ef152e3c08f8e/obelisk-handoffdeleted
No changes to the content.
migration/315cd79f97dae2f3669551dc03e0fd27-c801cbcf925c0a7b084ef152e3c08f8e/obelisk-upgradedeleted
No changes to the content.
migration/31a676fd9e1f69bd07380480ec879da0-9223532a537f698ef36f4dce6e922a6b/obelisk-handoffdeleted
No changes to the content.
migration/31a676fd9e1f69bd07380480ec879da0-9223532a537f698ef36f4dce6e922a6b/obelisk-upgradedeleted
No changes to the content.
migration/338b92f88c49c7c3a1d8ec231d9f7189-a4477746ae1a7024bc3cd0807180d418/obelisk-handoffdeleted
No changes to the content.
migration/338b92f88c49c7c3a1d8ec231d9f7189-a4477746ae1a7024bc3cd0807180d418/obelisk-upgradedeleted
No changes to the content.
migration/33da5c0e6705843afa6e39e65bfa0564-3ec562b7333839d48e9523aec595f3ab/obelisk-handoffdeleted
No changes to the content.
migration/33da5c0e6705843afa6e39e65bfa0564-3ec562b7333839d48e9523aec595f3ab/obelisk-upgradedeleted
No changes to the content.
migration/34d14d4a444d3bf1487ada6129815df4-afbd010add526d309dccee6895e42d0d/obelisk-handoffdeleted
No changes to the content.
migration/34d14d4a444d3bf1487ada6129815df4-afbd010add526d309dccee6895e42d0d/obelisk-upgradedeleted
No changes to the content.
migration/35acc1e0c4d9c02d60abd116f3df84ee-ffa62158ed6fdece012980e4ad25e6ac/obelisk-handoffdeleted
No changes to the content.
migration/35acc1e0c4d9c02d60abd116f3df84ee-ffa62158ed6fdece012980e4ad25e6ac/obelisk-upgradedeleted
No changes to the content.
migration/367616bd36eda757f251a5e8e9096acc-ddaa8e0e42a1ef00154d580a390c9f17/obelisk-handoffdeleted
No changes to the content.
migration/367616bd36eda757f251a5e8e9096acc-ddaa8e0e42a1ef00154d580a390c9f17/obelisk-upgradedeleted
No changes to the content.
migration/36cdb1c744c3036c2932f01d5fadd9f5-e7b566495114e160f1f4d722b7ed8174/obelisk-handoffdeleted
No changes to the content.
migration/36cdb1c744c3036c2932f01d5fadd9f5-e7b566495114e160f1f4d722b7ed8174/obelisk-upgradedeleted
No changes to the content.
migration/375acf7f2a3b3c487da2a6b30735d74d-3b614d291e262d0f281b54ff42a6bb66/obelisk-handoffdeleted
No changes to the content.
migration/375acf7f2a3b3c487da2a6b30735d74d-3b614d291e262d0f281b54ff42a6bb66/obelisk-upgradedeleted
No changes to the content.
migration/37c2ed0ba2cd54c0ec29eae9043bc4c8-190460dabd2b9773c3fe81902d0c8a62/obelisk-handoffdeleted
No changes to the content.
migration/37c2ed0ba2cd54c0ec29eae9043bc4c8-190460dabd2b9773c3fe81902d0c8a62/obelisk-upgradedeleted
No changes to the content.
migration/388d7d29a65c1713e07a654e91eb9caf-b6ffce85249f30616da76334c7bbec6e/obelisk-handoffdeleted
No changes to the content.
migration/388d7d29a65c1713e07a654e91eb9caf-b6ffce85249f30616da76334c7bbec6e/obelisk-upgradedeleted
No changes to the content.
migration/39df6544d6b035d4c77cc829729f9c19-9f6c8fd80ab3ff2dcc48bfd211c8b761/obelisk-handoffdeleted
No changes to the content.
migration/39df6544d6b035d4c77cc829729f9c19-9f6c8fd80ab3ff2dcc48bfd211c8b761/obelisk-upgradedeleted
No changes to the content.
migration/3a207630aa67e5df48d2b87d34db616b-8adb921f4dbb9d363bf6647d304e02fe/obelisk-handoffdeleted
No changes to the content.
migration/3a207630aa67e5df48d2b87d34db616b-8adb921f4dbb9d363bf6647d304e02fe/obelisk-upgradedeleted
No changes to the content.
migration/3b614d291e262d0f281b54ff42a6bb66-2e9a04a228106f62128ea5bd19d6b25e/obelisk-handoffdeleted
No changes to the content.
migration/3b614d291e262d0f281b54ff42a6bb66-2e9a04a228106f62128ea5bd19d6b25e/obelisk-upgradedeleted
No changes to the content.
migration/3bc53f3a28cb8f403cc41c11a37eec5d-cd86427cc2d5b2e931d7ab03deb19d20/obelisk-handoffdeleted
No changes to the content.
migration/3bc53f3a28cb8f403cc41c11a37eec5d-cd86427cc2d5b2e931d7ab03deb19d20/obelisk-upgradedeleted
No changes to the content.
migration/3bf8e28473fb05791c5790f8906e2609-45185a6f053557f93a13cb8cd03963a7/obelisk-handoffdeleted
No changes to the content.
migration/3bf8e28473fb05791c5790f8906e2609-45185a6f053557f93a13cb8cd03963a7/obelisk-upgradedeleted
No changes to the content.
migration/3c1fc501da00f467c9a48a1ddee2c2b0-cd5b54d21dd0fb868f48624d41021f47/obelisk-handoffdeleted
No changes to the content.
migration/3c1fc501da00f467c9a48a1ddee2c2b0-cd5b54d21dd0fb868f48624d41021f47/obelisk-upgradedeleted
No changes to the content.
migration/3c4b3152f0608d23d07240e2df3ff8da-c6baede3962454713b73acefcc92fe75/obelisk-handoffdeleted
No changes to the content.
migration/3c4b3152f0608d23d07240e2df3ff8da-c6baede3962454713b73acefcc92fe75/obelisk-upgradedeleted
No changes to the content.
migration/3c7755e495f20cfac5e4dabe78644c5a-51e25cf740f064faa0a29b8e2afcc109/obelisk-handoffdeleted
No changes to the content.
migration/3c7755e495f20cfac5e4dabe78644c5a-51e25cf740f064faa0a29b8e2afcc109/obelisk-upgradedeleted
No changes to the content.
migration/3c80eccfe80d0abd36b07bb11e69fc7a-b4f6596f2c16811442d8bb2961fbb721/obelisk-handoffdeleted
No changes to the content.
migration/3c80eccfe80d0abd36b07bb11e69fc7a-b4f6596f2c16811442d8bb2961fbb721/obelisk-upgradedeleted
No changes to the content.
migration/3cb52c2838303a362e9efb7c7eea37bd-aeafaa5d20bab4439a5d31f29023a839/obelisk-handoffdeleted
No changes to the content.
migration/3cb52c2838303a362e9efb7c7eea37bd-aeafaa5d20bab4439a5d31f29023a839/obelisk-upgradedeleted
No changes to the content.
migration/3da702ef7f531ad6db874ac3f85e9c06-73bcf3ed6593d074bd097cd43f5145d1/obelisk-handoffdeleted
No changes to the content.
migration/3da702ef7f531ad6db874ac3f85e9c06-73bcf3ed6593d074bd097cd43f5145d1/obelisk-upgradedeleted
No changes to the content.
migration/3da7d4a3b507d18097a90becf4dde9aa-e1ef432db54d9a6daa9bdeeb543262ae/obelisk-handoffdeleted
No changes to the content.
migration/3da7d4a3b507d18097a90becf4dde9aa-e1ef432db54d9a6daa9bdeeb543262ae/obelisk-upgradedeleted
No changes to the content.
migration/3daecb03985f83d8af466a9e0541782b-a2665cfd303a4a34a7bfa3b7d0d264bb/obelisk-handoffdeleted
No changes to the content.
migration/3daecb03985f83d8af466a9e0541782b-a2665cfd303a4a34a7bfa3b7d0d264bb/obelisk-upgradedeleted
No changes to the content.
migration/3e253c6beb567ba8f4c8086a76b70645-d6cacd7f4fab95c4b6aa2d6c1a4ad2a0/obelisk-handoffdeleted
No changes to the content.
migration/3e253c6beb567ba8f4c8086a76b70645-d6cacd7f4fab95c4b6aa2d6c1a4ad2a0/obelisk-upgradedeleted
No changes to the content.
migration/3e763ebe16cc3a261f5776ab1f1f6d9a-583ec22b9af66e8f629ee404307eb2dc/obelisk-handoffdeleted
No changes to the content.
migration/3e763ebe16cc3a261f5776ab1f1f6d9a-583ec22b9af66e8f629ee404307eb2dc/obelisk-upgradedeleted
No changes to the content.
migration/3e8a6968585d3d60f3b13652a386aec0-c118e1ee09ec8d9aa3edf04e211ae035/obelisk-handoffdeleted
No changes to the content.
migration/3e8a6968585d3d60f3b13652a386aec0-c118e1ee09ec8d9aa3edf04e211ae035/obelisk-upgradedeleted
No changes to the content.
migration/3ec562b7333839d48e9523aec595f3ab-7b9c28d09bd962e89b9715500f9e184c/obelisk-handoffdeleted
No changes to the content.
migration/3ec562b7333839d48e9523aec595f3ab-7b9c28d09bd962e89b9715500f9e184c/obelisk-upgradedeleted
No changes to the content.
migration/3f0687592a77c0c66193652e9cd981fd-fb81153791e49cd00850e91ff7418018/obelisk-handoffdeleted
No changes to the content.
migration/3f0687592a77c0c66193652e9cd981fd-fb81153791e49cd00850e91ff7418018/obelisk-upgradedeleted
No changes to the content.
migration/3f23549fba6f8e67ba36b4405e8680b3-a6633fc9687566aa84c3d5d5e2bff4fd/obelisk-handoffdeleted
No changes to the content.
migration/3f23549fba6f8e67ba36b4405e8680b3-a6633fc9687566aa84c3d5d5e2bff4fd/obelisk-upgradedeleted
No changes to the content.
migration/41e3ba178b727517aa1cedc8815abe86-1d084e187591225f0e8fa6fa824f8863/obelisk-handoffdeleted
No changes to the content.
migration/41e3ba178b727517aa1cedc8815abe86-1d084e187591225f0e8fa6fa824f8863/obelisk-upgradedeleted
No changes to the content.
migration/4205857df2e234a476ad56f84a33e6ed-db327f87e60d4e59bdbfd482e5abe985/obelisk-handoffdeleted
No changes to the content.
migration/4205857df2e234a476ad56f84a33e6ed-db327f87e60d4e59bdbfd482e5abe985/obelisk-upgradedeleted
No changes to the content.
migration/423088b98df50b986c9197af83c42a25-3a207630aa67e5df48d2b87d34db616b/obelisk-handoffdeleted
No changes to the content.
migration/423088b98df50b986c9197af83c42a25-3a207630aa67e5df48d2b87d34db616b/obelisk-upgradedeleted
No changes to the content.
migration/42357310c09e345f9360259c6c4102f2-ae8862f8b7292690c852111ca5659ce9/obelisk-handoffdeleted
No changes to the content.
migration/42357310c09e345f9360259c6c4102f2-ae8862f8b7292690c852111ca5659ce9/obelisk-upgradedeleted
No changes to the content.
migration/4344c1bd0ef04ebc055d5252f58b0bef-2f3ecb5cdb0ab839a49271d91dd7852a/obelisk-handoffdeleted
No changes to the content.
migration/4344c1bd0ef04ebc055d5252f58b0bef-2f3ecb5cdb0ab839a49271d91dd7852a/obelisk-upgradedeleted
No changes to the content.
migration/4509e2a908da9e497fa67acacdd107b6-1fe00204f9d2cd653ff2894eae3d9356/obelisk-handoffdeleted
No changes to the content.
migration/4509e2a908da9e497fa67acacdd107b6-1fe00204f9d2cd653ff2894eae3d9356/obelisk-upgradedeleted
No changes to the content.
migration/45185a6f053557f93a13cb8cd03963a7-cffcc6cab6080a35b7bf7c5c7facd6bc/obelisk-handoffdeleted
No changes to the content.
migration/45185a6f053557f93a13cb8cd03963a7-cffcc6cab6080a35b7bf7c5c7facd6bc/obelisk-upgradedeleted
No changes to the content.
migration/455279b6974b96a673613cd0ccc8ed54-b3ff195b0a90ef5900f9cef2ba75f2fe/obelisk-handoffdeleted
No changes to the content.
migration/455279b6974b96a673613cd0ccc8ed54-b3ff195b0a90ef5900f9cef2ba75f2fe/obelisk-upgradedeleted
No changes to the content.
migration/463646ba21b356f612539ea34178adf9-b3b107d406a6a7675cd5b9f52e5f7d8e/obelisk-handoffdeleted
No changes to the content.
migration/463646ba21b356f612539ea34178adf9-b3b107d406a6a7675cd5b9f52e5f7d8e/obelisk-upgradedeleted
No changes to the content.
migration/466a19f9cfa2a103467fe6627225d27f-c67f206b6d2626eb6d36b00122b52784/obelisk-handoffdeleted
No changes to the content.
migration/466a19f9cfa2a103467fe6627225d27f-c67f206b6d2626eb6d36b00122b52784/obelisk-upgradedeleted
No changes to the content.
migration/469a31d20d69da72e6a3a3ea2bb02f9d-75c9cd9763d0ed89c17d455f49d66a4f/obelisk-handoffdeleted
No changes to the content.
migration/469a31d20d69da72e6a3a3ea2bb02f9d-75c9cd9763d0ed89c17d455f49d66a4f/obelisk-upgradedeleted
No changes to the content.
migration/46aed07c1a61476dd245ff8e74c0559f-73e2573d9074884d7ae83106d55ad229/obelisk-handoffdeleted
No changes to the content.
migration/46aed07c1a61476dd245ff8e74c0559f-73e2573d9074884d7ae83106d55ad229/obelisk-upgradedeleted
No changes to the content.
migration/46f9c6c66e2bd8980402b6117ca40965-463646ba21b356f612539ea34178adf9/obelisk-handoffdeleted
No changes to the content.
migration/46f9c6c66e2bd8980402b6117ca40965-463646ba21b356f612539ea34178adf9/obelisk-upgradedeleted
No changes to the content.
migration/470df6504156dc940b8e7f89c148e619-a5297d8457aa4c327f35d4697f6cb66f/obelisk-handoffdeleted
No changes to the content.
migration/470df6504156dc940b8e7f89c148e619-a5297d8457aa4c327f35d4697f6cb66f/obelisk-upgradedeleted
No changes to the content.
migration/47357c6c23f049241902bf2e2e686ac8-d62d6d443d9c2261b7e09664398aa005/obelisk-handoffdeleted
No changes to the content.
migration/47357c6c23f049241902bf2e2e686ac8-d62d6d443d9c2261b7e09664398aa005/obelisk-upgradedeleted
No changes to the content.
migration/475f9a0d63e84e9cf13b8be3986cb603-b95c8d049256fb7360ca14b12acd8544/obelisk-handoffdeleted
No changes to the content.
migration/475f9a0d63e84e9cf13b8be3986cb603-b95c8d049256fb7360ca14b12acd8544/obelisk-upgradedeleted
No changes to the content.
migration/477a0bb12b48357d1e2b415c91d904e3-486d5218951605d14ec4a1046d3fe83e/obelisk-handoffdeleted
No changes to the content.
migration/477a0bb12b48357d1e2b415c91d904e3-486d5218951605d14ec4a1046d3fe83e/obelisk-upgradedeleted
No changes to the content.
migration/486d5218951605d14ec4a1046d3fe83e-90489c1a9f7edd46a070d6474dceac86/obelisk-handoffdeleted
No changes to the content.
migration/486d5218951605d14ec4a1046d3fe83e-90489c1a9f7edd46a070d6474dceac86/obelisk-upgradedeleted
No changes to the content.
migration/48c027da19d895ba03e7b9120f771291-29fd07af89cc31526fca00226ff52a82/obelisk-handoffdeleted
No changes to the content.
migration/48c027da19d895ba03e7b9120f771291-29fd07af89cc31526fca00226ff52a82/obelisk-upgradedeleted
No changes to the content.
migration/494be5819cd601fd2f0c20e1b23b84a3-c66bc5ba27dec52d144ceb0aa429e449/obelisk-handoffdeleted
No changes to the content.
migration/494be5819cd601fd2f0c20e1b23b84a3-c66bc5ba27dec52d144ceb0aa429e449/obelisk-upgradedeleted
No changes to the content.
migration/4a037879b8a542f1590cbb87b0242331-4344c1bd0ef04ebc055d5252f58b0bef/obelisk-handoffdeleted
No changes to the content.
migration/4a037879b8a542f1590cbb87b0242331-4344c1bd0ef04ebc055d5252f58b0bef/obelisk-upgradedeleted
No changes to the content.
migration/4ab915b764f38a1b0b4ae6f619f5c3fa-59e4a192c611a2a9f6736afde9fe1a0e/obelisk-handoffdeleted
No changes to the content.
migration/4ab915b764f38a1b0b4ae6f619f5c3fa-59e4a192c611a2a9f6736afde9fe1a0e/obelisk-upgradedeleted
No changes to the content.
migration/4ace4414d71235a291f7148f80a0b0f5-9705509619667aacf799e91927c16dc8/obelisk-handoffdeleted
No changes to the content.
migration/4ace4414d71235a291f7148f80a0b0f5-9705509619667aacf799e91927c16dc8/obelisk-upgradedeleted
No changes to the content.
migration/4aefa80392582ec03a19f946e752d331-cb98f93880e6dea74014976977d6eb93/obelisk-handoffdeleted
No changes to the content.
migration/4aefa80392582ec03a19f946e752d331-cb98f93880e6dea74014976977d6eb93/obelisk-upgradedeleted
No changes to the content.
migration/4b3f45ce8aeb17ef18d1d9502b74bb7e-4efbe4a73c260cca09fed7169e82a7ff/obelisk-handoffdeleted
No changes to the content.
migration/4b3f45ce8aeb17ef18d1d9502b74bb7e-4efbe4a73c260cca09fed7169e82a7ff/obelisk-upgradedeleted
No changes to the content.
migration/4b7a36dce2c1cf94554e12d8a7903269-dd6ca52a58ea6cda7b3eaa2e87bb13d9/obelisk-handoffdeleted
No changes to the content.
migration/4b7a36dce2c1cf94554e12d8a7903269-dd6ca52a58ea6cda7b3eaa2e87bb13d9/obelisk-upgradedeleted
No changes to the content.
migration/4c9372bf9aa6ebed1ea20abf3dbb0075-b641dd9c5359201200e483a784456cc2/obelisk-handoffdeleted
No changes to the content.
migration/4c9372bf9aa6ebed1ea20abf3dbb0075-b641dd9c5359201200e483a784456cc2/obelisk-upgradedeleted
No changes to the content.
migration/4d6197d8166de78f882376102e36300b-4205857df2e234a476ad56f84a33e6ed/obelisk-handoffdeleted
No changes to the content.
migration/4d6197d8166de78f882376102e36300b-4205857df2e234a476ad56f84a33e6ed/obelisk-upgradedeleted
No changes to the content.
migration/4d85ee8cdb0db20a5662b09567a2bbe7-b6425c7661af2116b912a558e9548013/obelisk-handoffdeleted
No changes to the content.
migration/4d85ee8cdb0db20a5662b09567a2bbe7-b6425c7661af2116b912a558e9548013/obelisk-upgradedeleted
No changes to the content.
migration/4da182e21be35feeee484dc85be7a075-14840816db4b5cfd5580ae099022604a/obelisk-handoffdeleted
No changes to the content.
migration/4da182e21be35feeee484dc85be7a075-14840816db4b5cfd5580ae099022604a/obelisk-upgradedeleted
No changes to the content.
migration/4db97ca86399c557e5ee0d04d0838acc-c203adc5fed9bf79f67df43d72a4631a/obelisk-handoffdeleted
No changes to the content.
migration/4db97ca86399c557e5ee0d04d0838acc-c203adc5fed9bf79f67df43d72a4631a/obelisk-upgradedeleted
No changes to the content.
migration/4e3e6e8b9d0f4194842e530438ff686f-b7e30314f9d0e69efdc84c7eb4e3bcc3/obelisk-handoffdeleted
No changes to the content.
migration/4e3e6e8b9d0f4194842e530438ff686f-b7e30314f9d0e69efdc84c7eb4e3bcc3/obelisk-upgradedeleted
No changes to the content.
migration/4e95e2f8ef50420371b71022c644e25d-8df9e256d8e43fa4e22d953024269b5b/obelisk-handoffdeleted
No changes to the content.
migration/4e95e2f8ef50420371b71022c644e25d-8df9e256d8e43fa4e22d953024269b5b/obelisk-upgradedeleted
No changes to the content.
migration/4efbe4a73c260cca09fed7169e82a7ff-315cd79f97dae2f3669551dc03e0fd27/obelisk-handoffdeleted
No changes to the content.
migration/4efbe4a73c260cca09fed7169e82a7ff-315cd79f97dae2f3669551dc03e0fd27/obelisk-upgradedeleted
No changes to the content.
migration/4fe321cf196b9cd25210c35e09e09d8f-56d7fd24c8a996e49bb26dd797819897/obelisk-handoffdeleted
No changes to the content.
migration/4fe321cf196b9cd25210c35e09e09d8f-56d7fd24c8a996e49bb26dd797819897/obelisk-upgradedeleted
No changes to the content.
migration/4ff5bf819ea43a638abbcfa071bbf3ef-975cd8245d06ad09e4fb176cfc9af5e0/obelisk-handoffdeleted
No changes to the content.
migration/4ff5bf819ea43a638abbcfa071bbf3ef-975cd8245d06ad09e4fb176cfc9af5e0/obelisk-upgradedeleted
No changes to the content.
migration/50b85e79010ad50ee275eaeba0df6f8d-e327773e1525eaa1eb2112dff8f41b26/obelisk-handoffdeleted
No changes to the content.
migration/50b85e79010ad50ee275eaeba0df6f8d-e327773e1525eaa1eb2112dff8f41b26/obelisk-upgradedeleted
No changes to the content.
migration/51c7d001730ddd3d76e0c8bb57038773-423088b98df50b986c9197af83c42a25/obelisk-handoffdeleted
No changes to the content.
migration/51c7d001730ddd3d76e0c8bb57038773-423088b98df50b986c9197af83c42a25/obelisk-upgradedeleted
No changes to the content.
migration/51e25cf740f064faa0a29b8e2afcc109-7bc4c944b24621967a6334f522437cc1/obelisk-handoffdeleted
No changes to the content.
migration/51e25cf740f064faa0a29b8e2afcc109-7bc4c944b24621967a6334f522437cc1/obelisk-upgradedeleted
No changes to the content.
migration/51f3d5068259f596b811450f0bf25419-f9716ad47c84e0b7ac7d426e8ad059f3/obelisk-handoffdeleted
No changes to the content.
migration/51f3d5068259f596b811450f0bf25419-f9716ad47c84e0b7ac7d426e8ad059f3/obelisk-upgradedeleted
No changes to the content.
migration/52330622ae996023b3f80a40991521a4-1df871cede0758cabe43971d9091279d/obelisk-handoffdeleted
No changes to the content.
migration/52330622ae996023b3f80a40991521a4-1df871cede0758cabe43971d9091279d/obelisk-upgradedeleted
No changes to the content.
migration/52df183d0f32d5a1e9ebe276b6d83d37-08dbdf23867a8efa680283ad251d3429/obelisk-handoffdeleted
No changes to the content.
migration/52df183d0f32d5a1e9ebe276b6d83d37-08dbdf23867a8efa680283ad251d3429/obelisk-upgradedeleted
No changes to the content.
migration/53d29061537ddaf7530aef88624ab266-9fe2922674fcee5e840c9f52cf534f88/obelisk-handoffdeleted
No changes to the content.
migration/53d29061537ddaf7530aef88624ab266-9fe2922674fcee5e840c9f52cf534f88/obelisk-upgradedeleted
No changes to the content.
migration/53fdf819333b86dfb485bf16a8f28db2-93fc625d41bae9fcf06b9febeacb686d/obelisk-handoffdeleted
No changes to the content.
migration/53fdf819333b86dfb485bf16a8f28db2-93fc625d41bae9fcf06b9febeacb686d/obelisk-upgradedeleted
No changes to the content.
migration/554c459ff2cced3e1b11241ed403890d-3543ea607791bc2e19419d22918823bd/obelisk-handoffdeleted
No changes to the content.
migration/554c459ff2cced3e1b11241ed403890d-3543ea607791bc2e19419d22918823bd/obelisk-upgradedeleted
No changes to the content.
migration/554c459ff2cced3e1b11241ed403890d-6a18939264224d6ce24c7426249edfea/obelisk-handoffdeleted
No changes to the content.
migration/554c459ff2cced3e1b11241ed403890d-6a18939264224d6ce24c7426249edfea/obelisk-upgradedeleted
No changes to the content.
migration/55cf43fb0d3868040c9efbf2f92d538a-e2706f337218a12a3bdddd18fa3f4cfd/obelisk-handoffdeleted
No changes to the content.
migration/55cf43fb0d3868040c9efbf2f92d538a-e2706f337218a12a3bdddd18fa3f4cfd/obelisk-upgradedeleted
No changes to the content.
migration/55d9c5eb3b86c9cb27966f849b2d32cf-0e4d0f0f0af0925474b0d772be2b145f/obelisk-handoffdeleted
No changes to the content.
migration/55d9c5eb3b86c9cb27966f849b2d32cf-0e4d0f0f0af0925474b0d772be2b145f/obelisk-upgradedeleted
No changes to the content.
migration/5631293b75143d170b8fca5579e15fee-0abd9d31c77be8c9a9e83bf1f73276f6/obelisk-handoffdeleted
No changes to the content.
migration/5631293b75143d170b8fca5579e15fee-0abd9d31c77be8c9a9e83bf1f73276f6/obelisk-upgradedeleted
No changes to the content.
migration/569227e5e7754c1890022850fd552292-ff1105290f89350bc9deb6eb907e0a53/obelisk-handoffdeleted
No changes to the content.
migration/569227e5e7754c1890022850fd552292-ff1105290f89350bc9deb6eb907e0a53/obelisk-upgradedeleted
No changes to the content.
migration/56d7fd24c8a996e49bb26dd797819897-61f734d4c59e46f03e92d2b86299c7c9/obelisk-handoffdeleted
No changes to the content.
migration/56d7fd24c8a996e49bb26dd797819897-61f734d4c59e46f03e92d2b86299c7c9/obelisk-upgradedeleted
No changes to the content.
migration/5734398c41e4eb5bb58d933ed2e12041-fb374b0721716a1e849e64daf6da73c4/obelisk-handoffdeleted
No changes to the content.
migration/5734398c41e4eb5bb58d933ed2e12041-fb374b0721716a1e849e64daf6da73c4/obelisk-upgradedeleted
No changes to the content.
migration/58391ba73c13d922e8a12116b28caad2-215b6810b09f219a5cb3842aacc88432/obelisk-handoffdeleted
No changes to the content.
migration/58391ba73c13d922e8a12116b28caad2-215b6810b09f219a5cb3842aacc88432/obelisk-upgradedeleted
No changes to the content.
migration/583ec22b9af66e8f629ee404307eb2dc-6c7f4af3693c31e1a2c6a2c3f189ddf5/obelisk-handoffdeleted
No changes to the content.
migration/583ec22b9af66e8f629ee404307eb2dc-6c7f4af3693c31e1a2c6a2c3f189ddf5/obelisk-upgradedeleted
No changes to the content.
migration/58479e482d3828ce44f2c8371ed9135a-174fa1072ee767be39b7b01aecea5714/obelisk-handoffdeleted
No changes to the content.
migration/58479e482d3828ce44f2c8371ed9135a-174fa1072ee767be39b7b01aecea5714/obelisk-upgradedeleted
No changes to the content.
migration/589eb89cdb09655c5edde4cd2a4deb80-c5a306045ad998f906f80748fe18487f/obelisk-handoffdeleted
No changes to the content.
migration/589eb89cdb09655c5edde4cd2a4deb80-c5a306045ad998f906f80748fe18487f/obelisk-upgradedeleted
No changes to the content.
migration/58f9d23d2cede2081dc6f6cfa2283f60-41e3ba178b727517aa1cedc8815abe86/obelisk-handoffdeleted
No changes to the content.
migration/58f9d23d2cede2081dc6f6cfa2283f60-41e3ba178b727517aa1cedc8815abe86/obelisk-upgradedeleted
No changes to the content.
migration/59742705e53838ae13066a2239a72040-95955d1dd0981ebb538ee941cde1f963/obelisk-handoffdeleted
No changes to the content.
migration/59742705e53838ae13066a2239a72040-95955d1dd0981ebb538ee941cde1f963/obelisk-upgradedeleted
No changes to the content.
migration/59e4a192c611a2a9f6736afde9fe1a0e-8143888349912db9780231c370ea2060/obelisk-handoffdeleted
No changes to the content.
migration/59e4a192c611a2a9f6736afde9fe1a0e-8143888349912db9780231c370ea2060/obelisk-upgradedeleted
No changes to the content.
migration/5a98cdb6c195e88beac878a3f311c5b5-66d79b4c393877a72aec18f227049207/obelisk-handoffdeleted
No changes to the content.
migration/5a98cdb6c195e88beac878a3f311c5b5-66d79b4c393877a72aec18f227049207/obelisk-upgradedeleted
No changes to the content.
migration/5b252c24612c2ba868580add9d9c19e3-6f104c322bbaff565981739406290402/obelisk-handoffdeleted
No changes to the content.
migration/5b252c24612c2ba868580add9d9c19e3-6f104c322bbaff565981739406290402/obelisk-upgradedeleted
No changes to the content.
migration/5b6770965bbef440db49b0703cd243a3-11f38b38c2d38004bb8a9dbfe2ef3e4a/obelisk-handoffdeleted
No changes to the content.
migration/5b6770965bbef440db49b0703cd243a3-11f38b38c2d38004bb8a9dbfe2ef3e4a/obelisk-upgradedeleted
No changes to the content.
migration/5cb98d0250bf5224b94e544a5140a54c-fa18f7522903a21b615dbee24c26bfbe/obelisk-handoffdeleted
No changes to the content.
migration/5cb98d0250bf5224b94e544a5140a54c-fa18f7522903a21b615dbee24c26bfbe/obelisk-upgradedeleted
No changes to the content.
migration/5d90abd974b4ec53091a8cb3fc2258ce-d40e0e3051a76c4c198cc11c2e8e4b7c/obelisk-handoffdeleted
No changes to the content.
migration/5d90abd974b4ec53091a8cb3fc2258ce-d40e0e3051a76c4c198cc11c2e8e4b7c/obelisk-upgradedeleted
No changes to the content.
migration/5f0d3f7480d67df7deebdb880726b356-4ab915b764f38a1b0b4ae6f619f5c3fa/obelisk-handoffdeleted
No changes to the content.
migration/5f0d3f7480d67df7deebdb880726b356-4ab915b764f38a1b0b4ae6f619f5c3fa/obelisk-upgradedeleted
No changes to the content.
migration/5f307639ccf6a64309166bfe58037397-702c65f35bc47641d60580d636ede330/obelisk-handoffdeleted
No changes to the content.
migration/5f307639ccf6a64309166bfe58037397-702c65f35bc47641d60580d636ede330/obelisk-upgradedeleted
No changes to the content.
migration/5f6fe243beb9fcc0c4117536022fc14c-f41b690c74938e347cf042cee2d4fc72/obelisk-handoffdeleted
No changes to the content.
migration/5f6fe243beb9fcc0c4117536022fc14c-f41b690c74938e347cf042cee2d4fc72/obelisk-upgradedeleted
No changes to the content.
migration/6095bdaccd933d319c84cde7983e2d10-477a0bb12b48357d1e2b415c91d904e3/obelisk-handoffdeleted
No changes to the content.
migration/6095bdaccd933d319c84cde7983e2d10-477a0bb12b48357d1e2b415c91d904e3/obelisk-upgradedeleted
No changes to the content.
migration/610dcf99f7eb8c8b591ff3f5f1722938-131e1d5cc8163ce9a174a8782be23fe7/obelisk-handoffdeleted
No changes to the content.
migration/610dcf99f7eb8c8b591ff3f5f1722938-131e1d5cc8163ce9a174a8782be23fe7/obelisk-upgradedeleted
No changes to the content.
migration/61f734d4c59e46f03e92d2b86299c7c9-02d0f8b5c7472e6f8a99ec2cfcb59807/obelisk-handoffdeleted
No changes to the content.
migration/61f734d4c59e46f03e92d2b86299c7c9-02d0f8b5c7472e6f8a99ec2cfcb59807/obelisk-upgradedeleted
No changes to the content.
migration/63422a9bade5c703461b600e03e227f0-01ddc6354698efa1ae5822da3be562dc/obelisk-handoffdeleted
No changes to the content.
migration/63422a9bade5c703461b600e03e227f0-01ddc6354698efa1ae5822da3be562dc/obelisk-upgradedeleted
No changes to the content.
migration/63ff9426130baa080f37400a86c55fdd-569227e5e7754c1890022850fd552292/obelisk-handoffdeleted
No changes to the content.
migration/63ff9426130baa080f37400a86c55fdd-569227e5e7754c1890022850fd552292/obelisk-upgradedeleted
No changes to the content.
migration/64ee9e40f4943e0122398e48019f5616-cd38e239c47fb92fabd867b7f86fc99a/obelisk-handoffdeleted
No changes to the content.
migration/64ee9e40f4943e0122398e48019f5616-cd38e239c47fb92fabd867b7f86fc99a/obelisk-upgradedeleted
No changes to the content.
migration/65071e255719af6389857646bc087d37-02fb88dab35884e09deef1721c1cfc13/obelisk-handoffdeleted
No changes to the content.
migration/65071e255719af6389857646bc087d37-02fb88dab35884e09deef1721c1cfc13/obelisk-upgradedeleted
No changes to the content.
migration/6558f8bda2aa17d76c509dde0a3dea56-2ccf977797628dc3b1c002927fedc7a8/obelisk-handoffdeleted
No changes to the content.
migration/6558f8bda2aa17d76c509dde0a3dea56-2ccf977797628dc3b1c002927fedc7a8/obelisk-upgradedeleted
No changes to the content.
migration/6566f0555737425bae9106d1a4a0a2dd-1f7fb90cb1e558f5285b2d19a25a1078/obelisk-handoffdeleted
No changes to the content.
migration/6566f0555737425bae9106d1a4a0a2dd-1f7fb90cb1e558f5285b2d19a25a1078/obelisk-upgradedeleted
No changes to the content.
migration/6620e6dc5622593e5f671127af9ade05-4ff5bf819ea43a638abbcfa071bbf3ef/obelisk-handoffdeleted
No changes to the content.
migration/6620e6dc5622593e5f671127af9ade05-4ff5bf819ea43a638abbcfa071bbf3ef/obelisk-upgradedeleted
No changes to the content.
migration/662eb30d6e4612f130edc3f6d37d92a2-94dd4eb45a4e7eb945027d5fd8eb4fa6/obelisk-handoffdeleted
No changes to the content.
migration/662eb30d6e4612f130edc3f6d37d92a2-94dd4eb45a4e7eb945027d5fd8eb4fa6/obelisk-upgradedeleted
No changes to the content.
migration/66a9b6b9e9bc4a5b0cfa78127479b231-88765caf54c2bf9f23ea4d05816a9f65/obelisk-handoffdeleted
No changes to the content.
migration/66a9b6b9e9bc4a5b0cfa78127479b231-88765caf54c2bf9f23ea4d05816a9f65/obelisk-upgradedeleted
No changes to the content.
migration/66d79b4c393877a72aec18f227049207-04dd95ecb889ac1b0a616ddfeec781c4/obelisk-handoffdeleted
No changes to the content.
migration/66d79b4c393877a72aec18f227049207-04dd95ecb889ac1b0a616ddfeec781c4/obelisk-upgradedeleted
No changes to the content.
migration/66f7a274206ad9f6d3c5701e4bcffc9d-2e7cdc2bea08bb2358219ddefef372e0/obelisk-handoffdeleted
No changes to the content.
migration/66f7a274206ad9f6d3c5701e4bcffc9d-2e7cdc2bea08bb2358219ddefef372e0/obelisk-upgradedeleted
No changes to the content.
migration/6708d14c71c475ac494808e75660a385-6095bdaccd933d319c84cde7983e2d10/obelisk-handoffdeleted
No changes to the content.
migration/6708d14c71c475ac494808e75660a385-6095bdaccd933d319c84cde7983e2d10/obelisk-upgradedeleted
No changes to the content.
migration/67173f110f2c54d135e6943b65118303-17089ea0edc0cf4b6f616936f8a06174/obelisk-handoffdeleted
No changes to the content.
migration/67173f110f2c54d135e6943b65118303-17089ea0edc0cf4b6f616936f8a06174/obelisk-upgradedeleted
No changes to the content.
migration/67bfa5b784a35e66875fb74ad84a38c0-f3ec62d09836804e39fad9d814137845/obelisk-handoffdeleted
No changes to the content.
migration/67bfa5b784a35e66875fb74ad84a38c0-f3ec62d09836804e39fad9d814137845/obelisk-upgradedeleted
No changes to the content.
migration/68cca18f813a16eb0cc2c3ed7fa08044-ee3dccc89ea6fdaaf9c1146b92861e90/obelisk-handoffdeleted
No changes to the content.
migration/68cca18f813a16eb0cc2c3ed7fa08044-ee3dccc89ea6fdaaf9c1146b92861e90/obelisk-upgradedeleted
No changes to the content.
migration/69537089a0e97845ffe05c73c3cc1536-e92786eaf56c32fd6b452c4a841d6317/obelisk-handoffdeleted
No changes to the content.
migration/69537089a0e97845ffe05c73c3cc1536-e92786eaf56c32fd6b452c4a841d6317/obelisk-upgradedeleted
No changes to the content.
migration/69cd775958e25e3b2cff7e4897f2a9bb-fca48edfdaa31b036176b97b04384682/obelisk-handoffdeleted
No changes to the content.
migration/69cd775958e25e3b2cff7e4897f2a9bb-fca48edfdaa31b036176b97b04384682/obelisk-upgradedeleted
No changes to the content.
migration/69fafe6ab155ff215b6d9d330f700ba1-6558f8bda2aa17d76c509dde0a3dea56/obelisk-handoffdeleted
No changes to the content.
migration/69fafe6ab155ff215b6d9d330f700ba1-6558f8bda2aa17d76c509dde0a3dea56/obelisk-upgradedeleted
No changes to the content.
migration/6a18939264224d6ce24c7426249edfea-e66afc8befac4d76b5780a960f768c31/obelisk-handoffdeleted
No changes to the content.
migration/6a18939264224d6ce24c7426249edfea-e66afc8befac4d76b5780a960f768c31/obelisk-upgradedeleted−15
@@ -1,15 +0,0 @@
1−# ob deploy: HTTPs support
3−Obelisk deployments now support HTTPs. You must upgrade the deployment repo
4−associated with the obelisk project as follows:
7−cd /your/project's/deployment/repo
8−echo True > enable_https
9−echo admin@yoursite.com > admin_email
10−echo https://yoursite.com/ > config/common/route
11−git add ... && git commit ...
15−If you do not wish to enable HTTPs, write `False` to `enable_https` instead.
migration/6c7f4af3693c31e1a2c6a2c3f189ddf5-388d7d29a65c1713e07a654e91eb9caf/obelisk-handoffdeleted
No changes to the content.
migration/6c7f4af3693c31e1a2c6a2c3f189ddf5-388d7d29a65c1713e07a654e91eb9caf/obelisk-upgradedeleted
No changes to the content.
migration/6da2e5b02ab780d12527640722d2b511-ca88f98cf9fb63d2feaef7fc19b30eca/obelisk-handoffdeleted
No changes to the content.
migration/6da2e5b02ab780d12527640722d2b511-ca88f98cf9fb63d2feaef7fc19b30eca/obelisk-upgradedeleted
No changes to the content.
migration/6dc299cb41f8977785a5d676cbcd32d7-237aeb7eee0ffed230234ee04e49569f/obelisk-handoffdeleted
No changes to the content.
migration/6dc299cb41f8977785a5d676cbcd32d7-237aeb7eee0ffed230234ee04e49569f/obelisk-upgradedeleted
No changes to the content.
migration/6f104c322bbaff565981739406290402-f98b82f5d142ce83733a3f18bdacb138/obelisk-handoffdeleted
No changes to the content.
migration/6f104c322bbaff565981739406290402-f98b82f5d142ce83733a3f18bdacb138/obelisk-upgradedeleted
No changes to the content.
migration/6f3a0f756847ee5aa208a1dc79404779-00c627540326314c7154cc209e8a71e9/obelisk-handoffdeleted
No changes to the content.
migration/6f3a0f756847ee5aa208a1dc79404779-00c627540326314c7154cc209e8a71e9/obelisk-upgradedeleted
No changes to the content.
migration/6fc44f180bb825d5b372444339681135-6dc299cb41f8977785a5d676cbcd32d7/obelisk-handoffdeleted
No changes to the content.
migration/6fc44f180bb825d5b372444339681135-6dc299cb41f8977785a5d676cbcd32d7/obelisk-upgradedeleted
No changes to the content.
migration/702c65f35bc47641d60580d636ede330-9217718d2b3b217dbba72e7091459548/obelisk-handoffdeleted
No changes to the content.
migration/702c65f35bc47641d60580d636ede330-9217718d2b3b217dbba72e7091459548/obelisk-upgradedeleted
No changes to the content.
migration/71a47d4d6856c1956c0d1c9de9af231f-bb9a87fc325204313d89dbfb689dba2f/obelisk-handoffdeleted
No changes to the content.
migration/71a47d4d6856c1956c0d1c9de9af231f-bb9a87fc325204313d89dbfb689dba2f/obelisk-upgradedeleted
No changes to the content.
migration/71c6959cf98e05d356ff798ada6db2b8-55d9c5eb3b86c9cb27966f849b2d32cf/obelisk-handoffdeleted
No changes to the content.
migration/71c6959cf98e05d356ff798ada6db2b8-55d9c5eb3b86c9cb27966f849b2d32cf/obelisk-upgradedeleted
No changes to the content.
migration/71da39c91abb23488021a1e9142507d5-16b24e1a12b93ea83d7656a09d5e3338/obelisk-handoffdeleted
No changes to the content.
migration/71da39c91abb23488021a1e9142507d5-16b24e1a12b93ea83d7656a09d5e3338/obelisk-upgradedeleted
No changes to the content.
migration/721a02f3a7549e7d6efeaed087bfacb5-52df183d0f32d5a1e9ebe276b6d83d37/obelisk-handoffdeleted
No changes to the content.
migration/721a02f3a7549e7d6efeaed087bfacb5-52df183d0f32d5a1e9ebe276b6d83d37/obelisk-upgradedeleted
No changes to the content.
migration/729aaf942e685bb37fdbd5e97293bbcb-7b2b9cefa7dd57d51b587c3501a1b9ef/obelisk-handoffdeleted
No changes to the content.
migration/729aaf942e685bb37fdbd5e97293bbcb-7b2b9cefa7dd57d51b587c3501a1b9ef/obelisk-upgradedeleted
No changes to the content.
migration/73bcf3ed6593d074bd097cd43f5145d1-375acf7f2a3b3c487da2a6b30735d74d/obelisk-handoffdeleted
No changes to the content.
migration/73bcf3ed6593d074bd097cd43f5145d1-375acf7f2a3b3c487da2a6b30735d74d/obelisk-upgradedeleted
No changes to the content.
migration/73e2573d9074884d7ae83106d55ad229-729aaf942e685bb37fdbd5e97293bbcb/obelisk-handoffdeleted
No changes to the content.
migration/73e2573d9074884d7ae83106d55ad229-729aaf942e685bb37fdbd5e97293bbcb/obelisk-upgradedeleted
No changes to the content.
migration/7447d29f4712c72458c049cdb9380753-e24a771ee59f24e45afc0a27307f2070/obelisk-handoffdeleted
No changes to the content.
migration/7447d29f4712c72458c049cdb9380753-e24a771ee59f24e45afc0a27307f2070/obelisk-upgradedeleted
No changes to the content.
migration/749df832c9305e1c6309a794b0c1b201-2619464637b85cb35376393fe612ddae/obelisk-handoffdeleted
No changes to the content.
migration/749df832c9305e1c6309a794b0c1b201-2619464637b85cb35376393fe612ddae/obelisk-upgradedeleted
No changes to the content.
migration/75c9cd9763d0ed89c17d455f49d66a4f-94372bb14f8afd19bce24f8402c7564c/obelisk-handoffdeleted
No changes to the content.
migration/75c9cd9763d0ed89c17d455f49d66a4f-94372bb14f8afd19bce24f8402c7564c/obelisk-upgradedeleted
No changes to the content.
migration/77a721a8fa97d1f84dd2af622089871b-cb2d040cc16752b1dc89eecf200ea798/obelisk-handoffdeleted
No changes to the content.
migration/77a721a8fa97d1f84dd2af622089871b-cb2d040cc16752b1dc89eecf200ea798/obelisk-upgradedeleted
No changes to the content.
migration/79357758056556793db0472562d62ff9-f15c9c2f894c8cc4fac07e2cdef47180/obelisk-handoffdeleted
No changes to the content.
migration/79357758056556793db0472562d62ff9-f15c9c2f894c8cc4fac07e2cdef47180/obelisk-upgradedeleted
No changes to the content.
migration/7adece557941a7d7ac7c150f77f758be-67173f110f2c54d135e6943b65118303/obelisk-handoffdeleted
No changes to the content.
migration/7adece557941a7d7ac7c150f77f758be-67173f110f2c54d135e6943b65118303/obelisk-upgradedeleted
No changes to the content.
migration/7b2b9cefa7dd57d51b587c3501a1b9ef-1269155fffe21926f3704d5077e04332/obelisk-handoffdeleted
No changes to the content.
migration/7b2b9cefa7dd57d51b587c3501a1b9ef-1269155fffe21926f3704d5077e04332/obelisk-upgradedeleted
No changes to the content.
migration/7b75ffdcd86b5a330d9c325ad5767393-97873167212295a0fdc1219102b6b600/obelisk-handoffdeleted
No changes to the content.
migration/7b75ffdcd86b5a330d9c325ad5767393-97873167212295a0fdc1219102b6b600/obelisk-upgradedeleted
No changes to the content.
migration/7b9c28d09bd962e89b9715500f9e184c-df71cd82e801ca701bf4bc44b80b6d50/obelisk-handoffdeleted
No changes to the content.
migration/7b9c28d09bd962e89b9715500f9e184c-df71cd82e801ca701bf4bc44b80b6d50/obelisk-upgradedeleted
No changes to the content.
migration/7bc4c944b24621967a6334f522437cc1-3e8a6968585d3d60f3b13652a386aec0/obelisk-handoffdeleted
No changes to the content.
migration/7bc4c944b24621967a6334f522437cc1-3e8a6968585d3d60f3b13652a386aec0/obelisk-upgradedeleted
No changes to the content.
migration/7c0ab1210424b615251ef57036d316c3-b8aa42d4f2e5ef7db9ba34ecf6c42079/obelisk-handoffdeleted
No changes to the content.
migration/7c0ab1210424b615251ef57036d316c3-b8aa42d4f2e5ef7db9ba34ecf6c42079/obelisk-upgradedeleted
No changes to the content.
migration/7c98ef4a123c1a580d368d14e54961b7-adad34a1075a2fd51e1a1c06ec9d002d/obelisk-handoffdeleted
No changes to the content.
migration/7c98ef4a123c1a580d368d14e54961b7-adad34a1075a2fd51e1a1c06ec9d002d/obelisk-upgradedeleted
No changes to the content.
migration/7ce32302cfbba8b7567a05144057f8a3-28c5fec3b7b0b14b3625d5c8f60bcf68/obelisk-handoffdeleted
No changes to the content.
migration/7ce32302cfbba8b7567a05144057f8a3-28c5fec3b7b0b14b3625d5c8f60bcf68/obelisk-upgradedeleted
No changes to the content.
migration/7cf814f7404638f1c1be662a24d7cfea-e609d945b642fd9d4ce99931e3699db7/obelisk-handoffdeleted
No changes to the content.
migration/7cf814f7404638f1c1be662a24d7cfea-e609d945b642fd9d4ce99931e3699db7/obelisk-upgradedeleted
No changes to the content.
migration/7dd60550d7d79bd3923d91d67ecb433a-46aed07c1a61476dd245ff8e74c0559f/obelisk-handoffdeleted
No changes to the content.
migration/7dd60550d7d79bd3923d91d67ecb433a-46aed07c1a61476dd245ff8e74c0559f/obelisk-upgradedeleted
No changes to the content.
migration/7f46d84c4d303f30602b920f96acf871-97c7e1ea2c1ddb0ef23d2e4a9279f65c/obelisk-handoffdeleted
No changes to the content.
migration/7f46d84c4d303f30602b920f96acf871-97c7e1ea2c1ddb0ef23d2e4a9279f65c/obelisk-upgradedeleted
No changes to the content.
migration/7fac40a2398039b364746989bb78798b-68cca18f813a16eb0cc2c3ed7fa08044/obelisk-handoffdeleted
No changes to the content.
migration/7fac40a2398039b364746989bb78798b-68cca18f813a16eb0cc2c3ed7fa08044/obelisk-upgradedeleted
No changes to the content.
migration/7fc381538805adac19c54b73ea118601-982c57eada4652019d0b0cf6ad355d25/obelisk-handoffdeleted
No changes to the content.
migration/7fc381538805adac19c54b73ea118601-982c57eada4652019d0b0cf6ad355d25/obelisk-upgradedeleted
No changes to the content.
migration/80cb6b08443d55bb512e4a35b4768b72-59742705e53838ae13066a2239a72040/obelisk-handoffdeleted
No changes to the content.
migration/80cb6b08443d55bb512e4a35b4768b72-59742705e53838ae13066a2239a72040/obelisk-upgradedeleted
No changes to the content.
migration/81223455459db28cdbc990c3d4e6eedd-71da39c91abb23488021a1e9142507d5/obelisk-handoffdeleted
No changes to the content.
migration/81223455459db28cdbc990c3d4e6eedd-71da39c91abb23488021a1e9142507d5/obelisk-upgradedeleted
No changes to the content.
migration/8143888349912db9780231c370ea2060-beaa30317dadbef830531237279cbca4/obelisk-handoffdeleted
No changes to the content.
migration/8143888349912db9780231c370ea2060-beaa30317dadbef830531237279cbca4/obelisk-upgradedeleted
No changes to the content.
migration/81f3dbeef0d78bfb523cd2ac113b8ad8-4ace4414d71235a291f7148f80a0b0f5/obelisk-handoffdeleted
No changes to the content.
migration/81f3dbeef0d78bfb523cd2ac113b8ad8-4ace4414d71235a291f7148f80a0b0f5/obelisk-upgradedeleted
No changes to the content.
migration/84f4d5c5491abb855d8dbe3acf3bc8e6-01fb7610e4184ad1b491267fcb0c7f43/obelisk-handoffdeleted
No changes to the content.
migration/84f4d5c5491abb855d8dbe3acf3bc8e6-01fb7610e4184ad1b491267fcb0c7f43/obelisk-upgradedeleted
No changes to the content.
migration/85c2c4fb8472d50eaa97aed0bdc9b142-3e253c6beb567ba8f4c8086a76b70645/obelisk-handoffdeleted
No changes to the content.
migration/85c2c4fb8472d50eaa97aed0bdc9b142-3e253c6beb567ba8f4c8086a76b70645/obelisk-upgradedeleted
No changes to the content.
migration/8746b8f08b75b2bb7c22d8f17f22d72d-e3b3014d7e0dc983fe118d32546654e5/obelisk-handoffdeleted
No changes to the content.
migration/8746b8f08b75b2bb7c22d8f17f22d72d-e3b3014d7e0dc983fe118d32546654e5/obelisk-upgradedeleted
No changes to the content.
migration/88046de6fbbdad3f6a8a5d311948ff9b-4a037879b8a542f1590cbb87b0242331/obelisk-handoffdeleted
No changes to the content.
migration/88046de6fbbdad3f6a8a5d311948ff9b-4a037879b8a542f1590cbb87b0242331/obelisk-upgradedeleted
No changes to the content.
migration/88439725720c7ba784750cda91157dfd-69cd775958e25e3b2cff7e4897f2a9bb/obelisk-handoffdeleted
No changes to the content.
migration/88439725720c7ba784750cda91157dfd-69cd775958e25e3b2cff7e4897f2a9bb/obelisk-upgradedeleted
No changes to the content.
migration/88765caf54c2bf9f23ea4d05816a9f65-52330622ae996023b3f80a40991521a4/obelisk-handoffdeleted
No changes to the content.
migration/88765caf54c2bf9f23ea4d05816a9f65-52330622ae996023b3f80a40991521a4/obelisk-upgradedeleted
No changes to the content.
migration/8911be694899014078c8e79fc858be45-33da5c0e6705843afa6e39e65bfa0564/obelisk-handoffdeleted
No changes to the content.
migration/8911be694899014078c8e79fc858be45-33da5c0e6705843afa6e39e65bfa0564/obelisk-upgradedeleted
No changes to the content.
migration/8a64ec5f2ee43d69607499f085560857-cba28ee4b736cf8ed43cb342ccaef12e/obelisk-handoffdeleted
No changes to the content.
migration/8a64ec5f2ee43d69607499f085560857-cba28ee4b736cf8ed43cb342ccaef12e/obelisk-upgradedeleted
No changes to the content.
migration/8adb921f4dbb9d363bf6647d304e02fe-bb2f504aa4f6f1ab8ed75697dc773efb/obelisk-handoffdeleted
No changes to the content.
migration/8adb921f4dbb9d363bf6647d304e02fe-bb2f504aa4f6f1ab8ed75697dc773efb/obelisk-upgradedeleted
No changes to the content.
migration/8b098f49e1fd1aa10ca22b9dc312644e-0ec6f67d94d3913cf3243d813238ec39/obelisk-handoffdeleted
No changes to the content.
migration/8b098f49e1fd1aa10ca22b9dc312644e-0ec6f67d94d3913cf3243d813238ec39/obelisk-upgradedeleted
No changes to the content.
migration/8c7718f94e2676c957fe844b7dc2637c-96c3d49b08a9d2cfb059197c60f49c05/obelisk-handoffdeleted
No changes to the content.
migration/8c7718f94e2676c957fe844b7dc2637c-96c3d49b08a9d2cfb059197c60f49c05/obelisk-upgradedeleted
No changes to the content.
migration/8c9599be2461288eee7e78d7a34643d8-053c0b2f84a7a2eadeb5c3f9575ffa0d/obelisk-handoffdeleted
No changes to the content.
migration/8c9599be2461288eee7e78d7a34643d8-053c0b2f84a7a2eadeb5c3f9575ffa0d/obelisk-upgradedeleted
No changes to the content.
migration/8d5dba70e93ae7e784ea238281842408-c93529e579e64263fd91663216fd3fe7/obelisk-handoffdeleted
No changes to the content.
migration/8d5dba70e93ae7e784ea238281842408-c93529e579e64263fd91663216fd3fe7/obelisk-upgradedeleted
No changes to the content.
migration/8dcf46725e839f4a5dcb7a9f0235e01b-0da1150f0e9fe57d1fafbb6cabe24fa1/obelisk-handoffdeleted
No changes to the content.
migration/8dcf46725e839f4a5dcb7a9f0235e01b-0da1150f0e9fe57d1fafbb6cabe24fa1/obelisk-upgradedeleted
No changes to the content.
migration/8df9e256d8e43fa4e22d953024269b5b-9d86cedf551a6ee24c5ae6779021b925/obelisk-handoffdeleted
No changes to the content.
migration/8df9e256d8e43fa4e22d953024269b5b-9d86cedf551a6ee24c5ae6779021b925/obelisk-upgradedeleted
No changes to the content.
migration/8e01c7fee83aa74229a77772d8c928f3-8911be694899014078c8e79fc858be45/obelisk-handoffdeleted
No changes to the content.
migration/8e01c7fee83aa74229a77772d8c928f3-8911be694899014078c8e79fc858be45/obelisk-upgradedeleted
No changes to the content.
migration/8e1e426afe242ea3079f160bccd94cf0-610dcf99f7eb8c8b591ff3f5f1722938/obelisk-handoffdeleted
No changes to the content.
migration/8e1e426afe242ea3079f160bccd94cf0-610dcf99f7eb8c8b591ff3f5f1722938/obelisk-upgradedeleted
No changes to the content.
migration/8fca2c4d6478ed8628925852b2af45bf-03b845f308e73a1567eb843dfca182d2/obelisk-handoffdeleted
No changes to the content.
migration/8fca2c4d6478ed8628925852b2af45bf-03b845f308e73a1567eb843dfca182d2/obelisk-upgradedeleted
No changes to the content.
migration/90489c1a9f7edd46a070d6474dceac86-7fac40a2398039b364746989bb78798b/obelisk-handoffdeleted
No changes to the content.
migration/90489c1a9f7edd46a070d6474dceac86-7fac40a2398039b364746989bb78798b/obelisk-upgradedeleted
No changes to the content.
migration/909b6b2066cbdc991e6c16455f13637c-1e36dc8817e2784df36d643b7499092d/obelisk-handoffdeleted
No changes to the content.
migration/909b6b2066cbdc991e6c16455f13637c-1e36dc8817e2784df36d643b7499092d/obelisk-upgradedeleted
No changes to the content.
migration/90b4e20464e08ade5f215f2a4ea28cc6-b7630e5f30252987bf899c74de3953ad/obelisk-handoffdeleted
No changes to the content.
migration/90b4e20464e08ade5f215f2a4ea28cc6-b7630e5f30252987bf899c74de3953ad/obelisk-upgradedeleted
No changes to the content.
migration/9217718d2b3b217dbba72e7091459548-88046de6fbbdad3f6a8a5d311948ff9b/obelisk-handoffdeleted
No changes to the content.
migration/9217718d2b3b217dbba72e7091459548-88046de6fbbdad3f6a8a5d311948ff9b/obelisk-upgradedeleted
No changes to the content.
migration/9223532a537f698ef36f4dce6e922a6b-d327ceb69d24e40dc11792840454cff9/obelisk-handoffdeleted
No changes to the content.
migration/9223532a537f698ef36f4dce6e922a6b-d327ceb69d24e40dc11792840454cff9/obelisk-upgradedeleted
No changes to the content.
migration/92ab733e8991f12cc12148f8d4e1b35d-e4b89dd259f3831bc60b56147b3586a6/obelisk-handoffdeleted
No changes to the content.
migration/92ab733e8991f12cc12148f8d4e1b35d-e4b89dd259f3831bc60b56147b3586a6/obelisk-upgradedeleted
No changes to the content.
migration/930e9213e072e87c207f93461bd3c96c-7f46d84c4d303f30602b920f96acf871/obelisk-handoffdeleted
No changes to the content.
migration/930e9213e072e87c207f93461bd3c96c-7f46d84c4d303f30602b920f96acf871/obelisk-upgradedeleted
No changes to the content.
migration/93f164bbd887f688fd49bb80afffccd6-f8eee9431c8b7a767d96da0a8cfae95d/obelisk-handoffdeleted
No changes to the content.
migration/93f164bbd887f688fd49bb80afffccd6-f8eee9431c8b7a767d96da0a8cfae95d/obelisk-upgradedeleted
No changes to the content.
migration/93fc625d41bae9fcf06b9febeacb686d-662eb30d6e4612f130edc3f6d37d92a2/obelisk-handoffdeleted
No changes to the content.
migration/93fc625d41bae9fcf06b9febeacb686d-662eb30d6e4612f130edc3f6d37d92a2/obelisk-upgradedeleted
No changes to the content.
migration/94252585266fa745a91733888e2f50b7-d207ab99328b8ece5fb27fa1f4dbf9f6/obelisk-handoffdeleted
No changes to the content.
migration/94252585266fa745a91733888e2f50b7-d207ab99328b8ece5fb27fa1f4dbf9f6/obelisk-upgradedeleted
No changes to the content.
migration/94372bb14f8afd19bce24f8402c7564c-7dd60550d7d79bd3923d91d67ecb433a/obelisk-handoffdeleted
No changes to the content.
migration/94372bb14f8afd19bce24f8402c7564c-7dd60550d7d79bd3923d91d67ecb433a/obelisk-upgradedeleted
No changes to the content.
migration/947784563e3a27cf6486bed9a3c52f15-25615a274650370633e8083ed19fbdd0/obelisk-handoffdeleted
No changes to the content.
migration/947784563e3a27cf6486bed9a3c52f15-25615a274650370633e8083ed19fbdd0/obelisk-upgradedeleted
No changes to the content.
migration/94dd4eb45a4e7eb945027d5fd8eb4fa6-e22c51145e08d4a089003460ae80a7f9/obelisk-handoffdeleted
No changes to the content.
migration/94dd4eb45a4e7eb945027d5fd8eb4fa6-e22c51145e08d4a089003460ae80a7f9/obelisk-upgradedeleted
No changes to the content.
migration/95955d1dd0981ebb538ee941cde1f963-07900e6c41ab9a78917f66fcf7e0d9b8/obelisk-handoffdeleted
No changes to the content.
migration/95955d1dd0981ebb538ee941cde1f963-07900e6c41ab9a78917f66fcf7e0d9b8/obelisk-upgradedeleted
No changes to the content.
migration/959ae2925bcd2b5beff631a8e7aeaf00-071f5b3326b8886de3eddc927b80eb10/obelisk-handoffdeleted
No changes to the content.
migration/959ae2925bcd2b5beff631a8e7aeaf00-071f5b3326b8886de3eddc927b80eb10/obelisk-upgradedeleted
No changes to the content.
migration/962e2bd1ae8d0c233f8da89ecebffe50-d6c090699acd25fc60213ff4bd9eebcf/obelisk-handoffdeleted
No changes to the content.
migration/962e2bd1ae8d0c233f8da89ecebffe50-d6c090699acd25fc60213ff4bd9eebcf/obelisk-upgradedeleted
No changes to the content.
migration/96c3d49b08a9d2cfb059197c60f49c05-6da2e5b02ab780d12527640722d2b511/obelisk-handoffdeleted
No changes to the content.
migration/96c3d49b08a9d2cfb059197c60f49c05-6da2e5b02ab780d12527640722d2b511/obelisk-upgradedeleted
No changes to the content.
migration/9705509619667aacf799e91927c16dc8-2773d4a82ca59b48faf036755e163a5f/obelisk-handoffdeleted
No changes to the content.
migration/9705509619667aacf799e91927c16dc8-2773d4a82ca59b48faf036755e163a5f/obelisk-upgradedeleted
No changes to the content.
migration/9715967793be68dfd8c9a7d631f8d589-d532356dfb65a4c8a39452d2ebca2516/obelisk-handoffdeleted
No changes to the content.
migration/9715967793be68dfd8c9a7d631f8d589-d532356dfb65a4c8a39452d2ebca2516/obelisk-upgradedeleted
No changes to the content.
migration/975cd8245d06ad09e4fb176cfc9af5e0-3f23549fba6f8e67ba36b4405e8680b3/obelisk-handoffdeleted
No changes to the content.
migration/975cd8245d06ad09e4fb176cfc9af5e0-3f23549fba6f8e67ba36b4405e8680b3/obelisk-upgradedeleted
No changes to the content.
migration/97873167212295a0fdc1219102b6b600-88439725720c7ba784750cda91157dfd/obelisk-handoffdeleted
No changes to the content.
migration/97873167212295a0fdc1219102b6b600-88439725720c7ba784750cda91157dfd/obelisk-upgradedeleted
No changes to the content.
migration/97c7e1ea2c1ddb0ef23d2e4a9279f65c-d747c3d0620b2034aca44265dd1c8c86/obelisk-handoffdeleted
No changes to the content.
migration/97c7e1ea2c1ddb0ef23d2e4a9279f65c-d747c3d0620b2034aca44265dd1c8c86/obelisk-upgradedeleted
No changes to the content.
migration/982c57eada4652019d0b0cf6ad355d25-6708d14c71c475ac494808e75660a385/obelisk-handoffdeleted
No changes to the content.
migration/982c57eada4652019d0b0cf6ad355d25-6708d14c71c475ac494808e75660a385/obelisk-upgradedeleted
No changes to the content.
migration/98629a336dcd5fa3524a09f8ea6ad636-8c9599be2461288eee7e78d7a34643d8/obelisk-handoffdeleted
No changes to the content.
migration/98629a336dcd5fa3524a09f8ea6ad636-8c9599be2461288eee7e78d7a34643d8/obelisk-upgradedeleted
No changes to the content.
migration/98da197f133bca81e533ab5ffbf4c82d-a0b418c582d5c6ef9e0cd9a19abe046e/obelisk-handoffdeleted
No changes to the content.
migration/98da197f133bca81e533ab5ffbf4c82d-a0b418c582d5c6ef9e0cd9a19abe046e/obelisk-upgradedeleted
No changes to the content.
migration/98f9e0bbd21e36b0f4daa440d11e7177-bab3871bcfbfcb3d2bad4495d44ae4f8/obelisk-handoffdeleted
No changes to the content.
migration/98f9e0bbd21e36b0f4daa440d11e7177-bab3871bcfbfcb3d2bad4495d44ae4f8/obelisk-upgradedeleted
No changes to the content.
migration/99aebbfcac51725464bc59571b7d71b8-34d14d4a444d3bf1487ada6129815df4/obelisk-handoffdeleted
No changes to the content.
migration/99aebbfcac51725464bc59571b7d71b8-34d14d4a444d3bf1487ada6129815df4/obelisk-upgradedeleted
No changes to the content.
migration/9b33a49f0c978e27b752fa457aca97cc-51f3d5068259f596b811450f0bf25419/obelisk-handoffdeleted
No changes to the content.
migration/9b33a49f0c978e27b752fa457aca97cc-51f3d5068259f596b811450f0bf25419/obelisk-upgradedeleted
No changes to the content.
migration/9b9d73736773550dde7d36de2498b029-69537089a0e97845ffe05c73c3cc1536/obelisk-handoffdeleted
No changes to the content.
migration/9b9d73736773550dde7d36de2498b029-69537089a0e97845ffe05c73c3cc1536/obelisk-upgradedeleted
No changes to the content.
migration/9c94cd459a25b5c2de56067c8fdac620-721a02f3a7549e7d6efeaed087bfacb5/obelisk-handoffdeleted
No changes to the content.
migration/9c94cd459a25b5c2de56067c8fdac620-721a02f3a7549e7d6efeaed087bfacb5/obelisk-upgradedeleted
No changes to the content.
migration/9cef2dd1885f16455ff9b6801ec99454-63ff9426130baa080f37400a86c55fdd/obelisk-handoffdeleted
No changes to the content.
migration/9cef2dd1885f16455ff9b6801ec99454-63ff9426130baa080f37400a86c55fdd/obelisk-upgradedeleted
No changes to the content.
migration/9d86cedf551a6ee24c5ae6779021b925-1c9bdb5c544f2e5432f549653a61dabe/obelisk-handoffdeleted
No changes to the content.
migration/9d86cedf551a6ee24c5ae6779021b925-1c9bdb5c544f2e5432f549653a61dabe/obelisk-upgradedeleted
No changes to the content.
migration/9e05cc6b81c6380ba0ac59bad1021cac-ce7f0d15d71d36d4bcf4fbadcdfa1b58/obelisk-handoffdeleted
No changes to the content.
migration/9e05cc6b81c6380ba0ac59bad1021cac-ce7f0d15d71d36d4bcf4fbadcdfa1b58/obelisk-upgradedeleted
No changes to the content.
migration/9e61f37dd79310b71c80ee166aeb4e80-466a19f9cfa2a103467fe6627225d27f/obelisk-handoffdeleted
No changes to the content.
migration/9e61f37dd79310b71c80ee166aeb4e80-466a19f9cfa2a103467fe6627225d27f/obelisk-upgradedeleted
No changes to the content.
migration/9f6c8fd80ab3ff2dcc48bfd211c8b761-24f151a674662ac47845237d7a9f6a4f/obelisk-handoffdeleted
No changes to the content.
migration/9f6c8fd80ab3ff2dcc48bfd211c8b761-24f151a674662ac47845237d7a9f6a4f/obelisk-upgradedeleted
No changes to the content.
migration/9f71fc9d2ed805fecbc8c4a3aae5685b-cb2197d0267b52385ee39bf4adcfe475/obelisk-handoffdeleted
No changes to the content.
migration/9f71fc9d2ed805fecbc8c4a3aae5685b-cb2197d0267b52385ee39bf4adcfe475/obelisk-upgradedeleted
No changes to the content.
migration/9fb504b182cbd8dfb666175b651e0b49-338b92f88c49c7c3a1d8ec231d9f7189/obelisk-handoffdeleted
No changes to the content.
migration/9fb504b182cbd8dfb666175b651e0b49-338b92f88c49c7c3a1d8ec231d9f7189/obelisk-upgradedeleted
No changes to the content.
migration/9fe2922674fcee5e840c9f52cf534f88-ac92878eb85c5283bcc5f3f34cd35aa6/obelisk-handoffdeleted
No changes to the content.
migration/9fe2922674fcee5e840c9f52cf534f88-ac92878eb85c5283bcc5f3f34cd35aa6/obelisk-upgradedeleted
No changes to the content.
migration/a00870cfca85ff8dae5db3a78f5a227d-c2502429502b46133a749f021d188cf0/obelisk-handoffdeleted
No changes to the content.
migration/a00870cfca85ff8dae5db3a78f5a227d-c2502429502b46133a749f021d188cf0/obelisk-upgradedeleted
No changes to the content.
migration/a080b8549e32f21fec11084f4ab1e052-bd7c24fc03bf82e5a990515531a69147/obelisk-handoffdeleted
No changes to the content.
migration/a080b8549e32f21fec11084f4ab1e052-bd7c24fc03bf82e5a990515531a69147/obelisk-upgradedeleted
No changes to the content.
migration/a08aebb6f40fb45d174b229532314ac4-1c1c3f2b4426d5d26377eef08dbccb3c/obelisk-handoffdeleted
No changes to the content.
migration/a08aebb6f40fb45d174b229532314ac4-1c1c3f2b4426d5d26377eef08dbccb3c/obelisk-upgradedeleted
No changes to the content.
migration/a0b418c582d5c6ef9e0cd9a19abe046e-63422a9bade5c703461b600e03e227f0/obelisk-handoffdeleted
No changes to the content.
migration/a0b418c582d5c6ef9e0cd9a19abe046e-63422a9bade5c703461b600e03e227f0/obelisk-upgradedeleted
No changes to the content.
migration/a0f5ac2ff5c6a957e565f898a9fc8bfb-bf3fbc8db3d6fd42a37982dfb5a30b5c/obelisk-handoffdeleted
No changes to the content.
migration/a0f5ac2ff5c6a957e565f898a9fc8bfb-bf3fbc8db3d6fd42a37982dfb5a30b5c/obelisk-upgradedeleted
No changes to the content.
migration/a262678b7d849de5a9732d06199666ae-ebb95c5864d1d1d2f78fbf7cc8235dac/obelisk-handoffdeleted
No changes to the content.
migration/a262678b7d849de5a9732d06199666ae-ebb95c5864d1d1d2f78fbf7cc8235dac/obelisk-upgradedeleted
No changes to the content.
migration/a2665cfd303a4a34a7bfa3b7d0d264bb-aff3f143ddaa4ed3ffad873d6638e277/obelisk-handoffdeleted
No changes to the content.
migration/a2665cfd303a4a34a7bfa3b7d0d264bb-aff3f143ddaa4ed3ffad873d6638e277/obelisk-upgradedeleted
No changes to the content.
migration/a2b33f8dc1f90b8dddce942b174be5b8-00a480749e96ef7e21fbe8f4943152b1/obelisk-handoffdeleted
No changes to the content.
migration/a2b33f8dc1f90b8dddce942b174be5b8-00a480749e96ef7e21fbe8f4943152b1/obelisk-upgradedeleted
No changes to the content.
migration/a2bdbf1985b75442e78e84523c4ced5f-48c027da19d895ba03e7b9120f771291/obelisk-handoffdeleted
No changes to the content.
migration/a2bdbf1985b75442e78e84523c4ced5f-48c027da19d895ba03e7b9120f771291/obelisk-upgradedeleted
No changes to the content.
migration/a34d758508a0a5d08bc10e76482c4d11-8fca2c4d6478ed8628925852b2af45bf/obelisk-handoffdeleted
No changes to the content.
migration/a34d758508a0a5d08bc10e76482c4d11-8fca2c4d6478ed8628925852b2af45bf/obelisk-upgradedeleted
No changes to the content.
migration/a4477746ae1a7024bc3cd0807180d418-fb5110e527cf77c568bcae7d435ee035/obelisk-handoffdeleted
No changes to the content.
migration/a4477746ae1a7024bc3cd0807180d418-fb5110e527cf77c568bcae7d435ee035/obelisk-upgradedeleted
No changes to the content.
migration/a5297d8457aa4c327f35d4697f6cb66f-2f928f9c4a137186f808a231c9e3c141/obelisk-handoffdeleted
No changes to the content.
migration/a5297d8457aa4c327f35d4697f6cb66f-2f928f9c4a137186f808a231c9e3c141/obelisk-upgradedeleted
No changes to the content.
migration/a536d01b9c489f5e00e30abf27427da0-b8a8ffc909e5fc350d9f8a6a90e7b3d9/obelisk-handoffdeleted
No changes to the content.
migration/a536d01b9c489f5e00e30abf27427da0-b8a8ffc909e5fc350d9f8a6a90e7b3d9/obelisk-upgradedeleted
No changes to the content.
migration/a5904e3a899e346fe2fe26314f69c075-e4513b485b6ba8b7f4bd34b12458ff0c/obelisk-handoffdeleted
No changes to the content.
migration/a5904e3a899e346fe2fe26314f69c075-e4513b485b6ba8b7f4bd34b12458ff0c/obelisk-upgradedeleted
No changes to the content.
migration/a5bbc0b9ceab9c3f7ca32a7da8c1f685-3c4b3152f0608d23d07240e2df3ff8da/obelisk-handoffdeleted
No changes to the content.
migration/a5bbc0b9ceab9c3f7ca32a7da8c1f685-3c4b3152f0608d23d07240e2df3ff8da/obelisk-upgradedeleted
No changes to the content.
migration/a5e40d67714a1b2daa06e3fb3293216d-04a5ae41e8fcef5f719cb84d01430382/obelisk-handoffdeleted
No changes to the content.
migration/a5e40d67714a1b2daa06e3fb3293216d-04a5ae41e8fcef5f719cb84d01430382/obelisk-upgradedeleted
No changes to the content.
migration/a632452cf9c5956becd1a40512472b43-d6a3ea5f7eb3c95f5e5ea09fb1330270/obelisk-handoffdeleted
No changes to the content.
migration/a632452cf9c5956becd1a40512472b43-d6a3ea5f7eb3c95f5e5ea09fb1330270/obelisk-upgradedeleted
No changes to the content.
migration/a6633fc9687566aa84c3d5d5e2bff4fd-b5cab336f6244293913433101cd0feff/obelisk-handoffdeleted
No changes to the content.
migration/a6633fc9687566aa84c3d5d5e2bff4fd-b5cab336f6244293913433101cd0feff/obelisk-upgradedeleted
No changes to the content.
migration/a6d50c7e756dfd1e3ae891111b81a1ae-270b3b3f7bc510c692e3253a895f122a/obelisk-handoffdeleted
No changes to the content.
migration/a6d50c7e756dfd1e3ae891111b81a1ae-270b3b3f7bc510c692e3253a895f122a/obelisk-upgradedeleted
No changes to the content.
migration/a7c7b80a875d1863f027c97eb433b884-cbe155a3e856fb7eaad0bd18feb408be/obelisk-handoffdeleted
No changes to the content.
migration/a7c7b80a875d1863f027c97eb433b884-cbe155a3e856fb7eaad0bd18feb408be/obelisk-upgradedeleted
No changes to the content.
migration/a808a04519bbf2874e41028ded9c180c-8e1e426afe242ea3079f160bccd94cf0/obelisk-handoffdeleted
No changes to the content.
migration/a808a04519bbf2874e41028ded9c180c-8e1e426afe242ea3079f160bccd94cf0/obelisk-upgradedeleted
No changes to the content.
migration/a825fbb74e8d050a5ce10ec4c62b83f5-c3298d81428117be58196b80853e3c7b/obelisk-handoffdeleted
No changes to the content.
migration/a825fbb74e8d050a5ce10ec4c62b83f5-c3298d81428117be58196b80853e3c7b/obelisk-upgradedeleted
No changes to the content.
migration/a826f01311fe00ef5cf87568832605d3-9fb504b182cbd8dfb666175b651e0b49/obelisk-handoffdeleted
No changes to the content.
migration/a826f01311fe00ef5cf87568832605d3-9fb504b182cbd8dfb666175b651e0b49/obelisk-upgradedeleted
No changes to the content.
migration/a878ad346b9305ad2ae3fd85410a7ed7-0f78d9d6875933336bbf0c1c8888b73f/obelisk-handoffdeleted
No changes to the content.
migration/a878ad346b9305ad2ae3fd85410a7ed7-0f78d9d6875933336bbf0c1c8888b73f/obelisk-upgradedeleted
No changes to the content.
migration/a8ebe201ab7a7b0211de41b14a95192e-65071e255719af6389857646bc087d37/obelisk-handoffdeleted
No changes to the content.
migration/a8ebe201ab7a7b0211de41b14a95192e-65071e255719af6389857646bc087d37/obelisk-upgradedeleted
No changes to the content.
migration/a96d491705acc139315264fd340d228f-be615dc4d60c9d8710fbd120857c2fa1/obelisk-handoffdeleted
No changes to the content.
migration/a96d491705acc139315264fd340d228f-be615dc4d60c9d8710fbd120857c2fa1/obelisk-upgradedeleted
No changes to the content.
migration/aa8e6712fd46824acdea303068634078-dc95f39fb27634ccbca7318ff2065608/obelisk-handoffdeleted
No changes to the content.
migration/aa8e6712fd46824acdea303068634078-dc95f39fb27634ccbca7318ff2065608/obelisk-upgradedeleted
No changes to the content.
migration/aaf979dd0121603a8b48127e1ea47c7d-4b7a36dce2c1cf94554e12d8a7903269/obelisk-handoffdeleted
No changes to the content.
migration/aaf979dd0121603a8b48127e1ea47c7d-4b7a36dce2c1cf94554e12d8a7903269/obelisk-upgradedeleted
No changes to the content.
migration/abdb013baf130e1bd7e7fd04e535c44c-39df6544d6b035d4c77cc829729f9c19/obelisk-handoffdeleted
No changes to the content.
migration/abdb013baf130e1bd7e7fd04e535c44c-39df6544d6b035d4c77cc829729f9c19/obelisk-upgradedeleted
No changes to the content.
migration/ac5e28caddd6832d0bf1f7445a4a6a28-e01cc01684deaf4c75ad5d65270bf3d5/obelisk-handoffdeleted
No changes to the content.
migration/ac5e28caddd6832d0bf1f7445a4a6a28-e01cc01684deaf4c75ad5d65270bf3d5/obelisk-upgradedeleted
No changes to the content.
migration/ac92878eb85c5283bcc5f3f34cd35aa6-145650b66e83adf5bdb8261593076379/obelisk-handoffdeleted
No changes to the content.
migration/ac92878eb85c5283bcc5f3f34cd35aa6-145650b66e83adf5bdb8261593076379/obelisk-upgradedeleted
No changes to the content.
migration/adad34a1075a2fd51e1a1c06ec9d002d-930e9213e072e87c207f93461bd3c96c/obelisk-handoffdeleted
No changes to the content.
migration/adad34a1075a2fd51e1a1c06ec9d002d-930e9213e072e87c207f93461bd3c96c/obelisk-upgradedeleted
No changes to the content.
migration/ae4328daeb7d2c52c534a687fbd184b6-3e763ebe16cc3a261f5776ab1f1f6d9a/obelisk-handoffdeleted
No changes to the content.
migration/ae4328daeb7d2c52c534a687fbd184b6-3e763ebe16cc3a261f5776ab1f1f6d9a/obelisk-upgradedeleted
No changes to the content.
migration/ae824b83b569b3b23b8e198190371ca0-81f3dbeef0d78bfb523cd2ac113b8ad8/obelisk-handoffdeleted
No changes to the content.
migration/ae824b83b569b3b23b8e198190371ca0-81f3dbeef0d78bfb523cd2ac113b8ad8/obelisk-upgradedeleted
No changes to the content.
migration/ae8862f8b7292690c852111ca5659ce9-ae4328daeb7d2c52c534a687fbd184b6/obelisk-handoffdeleted
No changes to the content.
migration/ae8862f8b7292690c852111ca5659ce9-ae4328daeb7d2c52c534a687fbd184b6/obelisk-upgradedeleted
No changes to the content.
migration/aeafaa5d20bab4439a5d31f29023a839-79357758056556793db0472562d62ff9/obelisk-handoffdeleted
No changes to the content.
migration/aeafaa5d20bab4439a5d31f29023a839-79357758056556793db0472562d62ff9/obelisk-upgradedeleted
No changes to the content.
migration/aef6ac052515a869c7d3061d4ccc69dd-15f3f3f517b38664131b85da0594522f/obelisk-handoffdeleted
No changes to the content.
migration/aef6ac052515a869c7d3061d4ccc69dd-15f3f3f517b38664131b85da0594522f/obelisk-upgradedeleted
No changes to the content.
migration/afbd010add526d309dccee6895e42d0d-6f3a0f756847ee5aa208a1dc79404779/obelisk-handoffdeleted
No changes to the content.
migration/afbd010add526d309dccee6895e42d0d-6f3a0f756847ee5aa208a1dc79404779/obelisk-upgradedeleted
No changes to the content.
migration/aff3f143ddaa4ed3ffad873d6638e277-6fc44f180bb825d5b372444339681135/obelisk-handoffdeleted
No changes to the content.
migration/aff3f143ddaa4ed3ffad873d6638e277-6fc44f180bb825d5b372444339681135/obelisk-upgradedeleted
No changes to the content.
migration/b0c1d039514a686529561f186332c91e-a878ad346b9305ad2ae3fd85410a7ed7/obelisk-handoffdeleted
No changes to the content.
migration/b0c1d039514a686529561f186332c91e-a878ad346b9305ad2ae3fd85410a7ed7/obelisk-upgradedeleted
No changes to the content.
migration/b1692927da5ed59af72fac5be8094fa2-d5ba6f13296205e5bd88ca2756107df0/obelisk-handoffdeleted
No changes to the content.
migration/b1692927da5ed59af72fac5be8094fa2-d5ba6f13296205e5bd88ca2756107df0/obelisk-upgradedeleted
No changes to the content.
migration/b2282679f6f63cec89d921c3dd512d1e-1f09fcf196bfe90ed52f113c38ffbfdb/obelisk-handoffdeleted
No changes to the content.
migration/b2282679f6f63cec89d921c3dd512d1e-1f09fcf196bfe90ed52f113c38ffbfdb/obelisk-upgradedeleted
No changes to the content.
migration/b3b107d406a6a7675cd5b9f52e5f7d8e-0d3b4cfe9b4c72b830780a4c44942176/obelisk-handoffdeleted
No changes to the content.
migration/b3b107d406a6a7675cd5b9f52e5f7d8e-0d3b4cfe9b4c72b830780a4c44942176/obelisk-upgradedeleted
No changes to the content.
migration/b3ff195b0a90ef5900f9cef2ba75f2fe-24e0d027f4160a6478c1356e51f419cf/obelisk-handoffdeleted
No changes to the content.
migration/b3ff195b0a90ef5900f9cef2ba75f2fe-24e0d027f4160a6478c1356e51f419cf/obelisk-upgradedeleted
No changes to the content.
migration/b4f6596f2c16811442d8bb2961fbb721-3c7755e495f20cfac5e4dabe78644c5a/obelisk-handoffdeleted
No changes to the content.
migration/b4f6596f2c16811442d8bb2961fbb721-3c7755e495f20cfac5e4dabe78644c5a/obelisk-upgradedeleted
No changes to the content.
migration/b5cab336f6244293913433101cd0feff-8746b8f08b75b2bb7c22d8f17f22d72d/obelisk-handoffdeleted
No changes to the content.
migration/b5cab336f6244293913433101cd0feff-8746b8f08b75b2bb7c22d8f17f22d72d/obelisk-upgradedeleted
No changes to the content.
migration/b641dd9c5359201200e483a784456cc2-cc4307fc88e3486b1c3f9ce07db95808/obelisk-handoffdeleted
No changes to the content.
migration/b641dd9c5359201200e483a784456cc2-cc4307fc88e3486b1c3f9ce07db95808/obelisk-upgradedeleted
No changes to the content.
migration/b6425c7661af2116b912a558e9548013-4aefa80392582ec03a19f946e752d331/obelisk-handoffdeleted
No changes to the content.
migration/b6425c7661af2116b912a558e9548013-4aefa80392582ec03a19f946e752d331/obelisk-upgradedeleted
No changes to the content.
migration/b68a785fbf27a63334ef1d1fe82b2dac-d6b34eba6ed4f89875a6615fe2c41ec2/obelisk-handoffdeleted
No changes to the content.
migration/b68a785fbf27a63334ef1d1fe82b2dac-d6b34eba6ed4f89875a6615fe2c41ec2/obelisk-upgradedeleted
No changes to the content.
migration/b6ffce85249f30616da76334c7bbec6e-66a9b6b9e9bc4a5b0cfa78127479b231/obelisk-handoffdeleted
No changes to the content.
migration/b6ffce85249f30616da76334c7bbec6e-66a9b6b9e9bc4a5b0cfa78127479b231/obelisk-upgradedeleted
No changes to the content.
migration/b7630e5f30252987bf899c74de3953ad-3f0687592a77c0c66193652e9cd981fd/obelisk-handoffdeleted
No changes to the content.
migration/b7630e5f30252987bf899c74de3953ad-3f0687592a77c0c66193652e9cd981fd/obelisk-upgradedeleted
No changes to the content.
migration/b7e30314f9d0e69efdc84c7eb4e3bcc3-e4051219d89b3c9a8350fe824ad96a82/obelisk-handoffdeleted
No changes to the content.
migration/b7e30314f9d0e69efdc84c7eb4e3bcc3-e4051219d89b3c9a8350fe824ad96a82/obelisk-upgradedeleted
No changes to the content.
migration/b82e9c3fe22feff4bb3a6be49943fd6c-fbb3eb3209281031dc5183d289eb4e75/obelisk-handoffdeleted
No changes to the content.
migration/b82e9c3fe22feff4bb3a6be49943fd6c-fbb3eb3209281031dc5183d289eb4e75/obelisk-upgradedeleted
No changes to the content.
migration/b8a8ffc909e5fc350d9f8a6a90e7b3d9-aef6ac052515a869c7d3061d4ccc69dd/obelisk-handoffdeleted
No changes to the content.
migration/b8a8ffc909e5fc350d9f8a6a90e7b3d9-aef6ac052515a869c7d3061d4ccc69dd/obelisk-upgradedeleted
No changes to the content.
migration/b8aa42d4f2e5ef7db9ba34ecf6c42079-37c2ed0ba2cd54c0ec29eae9043bc4c8/obelisk-handoffdeleted
No changes to the content.
migration/b8aa42d4f2e5ef7db9ba34ecf6c42079-37c2ed0ba2cd54c0ec29eae9043bc4c8/obelisk-upgradedeleted
No changes to the content.
migration/b95c8d049256fb7360ca14b12acd8544-e7b17aa124e17c357cead8081a58f089/obelisk-handoffdeleted
No changes to the content.
migration/b95c8d049256fb7360ca14b12acd8544-e7b17aa124e17c357cead8081a58f089/obelisk-upgradedeleted
No changes to the content.
migration/ba0ccd5ef6110f6c5133d9d6ea6277f0-e78ec85bec14f4784faeef4d8d3e4d0a/obelisk-handoffdeleted
No changes to the content.
migration/ba0ccd5ef6110f6c5133d9d6ea6277f0-e78ec85bec14f4784faeef4d8d3e4d0a/obelisk-upgradedeleted
No changes to the content.
migration/ba4829dc61dcc12bcafd8de5fc8a76dc-2164344be67da5d0e57052c15f30646d/obelisk-handoffdeleted
No changes to the content.
migration/ba4829dc61dcc12bcafd8de5fc8a76dc-2164344be67da5d0e57052c15f30646d/obelisk-upgradedeleted
No changes to the content.
migration/bab3871bcfbfcb3d2bad4495d44ae4f8-9cef2dd1885f16455ff9b6801ec99454/obelisk-handoffdeleted
No changes to the content.
migration/bab3871bcfbfcb3d2bad4495d44ae4f8-9cef2dd1885f16455ff9b6801ec99454/obelisk-upgradedeleted
No changes to the content.
migration/bb2f504aa4f6f1ab8ed75697dc773efb-bcd13da3a7fba8514084c1a9dbeabb31/obelisk-handoffdeleted
No changes to the content.
migration/bb2f504aa4f6f1ab8ed75697dc773efb-bcd13da3a7fba8514084c1a9dbeabb31/obelisk-upgradedeleted
No changes to the content.
migration/bb9a87fc325204313d89dbfb689dba2f-d2d86ce0ca16b143b49374302a9e9e2f/obelisk-handoffdeleted
No changes to the content.
migration/bb9a87fc325204313d89dbfb689dba2f-d2d86ce0ca16b143b49374302a9e9e2f/obelisk-upgradedeleted
No changes to the content.
migration/bc7688ff47218c0e13d02d917b03caa0-2bdd4221307cafa3e98c4d3017cdc912/obelisk-handoffdeleted
No changes to the content.
migration/bc7688ff47218c0e13d02d917b03caa0-2bdd4221307cafa3e98c4d3017cdc912/obelisk-upgradedeleted
No changes to the content.
migration/bcd13da3a7fba8514084c1a9dbeabb31-8dcf46725e839f4a5dcb7a9f0235e01b/obelisk-handoffdeleted
No changes to the content.
migration/bcd13da3a7fba8514084c1a9dbeabb31-8dcf46725e839f4a5dcb7a9f0235e01b/obelisk-upgradedeleted
No changes to the content.
migration/bd6728737dffcc3505d30ada344e2f4b-1cc8d98f6f61441570fdde2d697e6e3c/obelisk-handoffdeleted
No changes to the content.
migration/bd6728737dffcc3505d30ada344e2f4b-1cc8d98f6f61441570fdde2d697e6e3c/obelisk-upgradedeleted
No changes to the content.
migration/bd7c24fc03bf82e5a990515531a69147-a5e40d67714a1b2daa06e3fb3293216d/obelisk-handoffdeleted
No changes to the content.
migration/bd7c24fc03bf82e5a990515531a69147-a5e40d67714a1b2daa06e3fb3293216d/obelisk-upgradedeleted
No changes to the content.
migration/bd8f5fa095c3eb19b87d85247b36f1df-5d90abd974b4ec53091a8cb3fc2258ce/obelisk-handoffdeleted
No changes to the content.
migration/bd8f5fa095c3eb19b87d85247b36f1df-5d90abd974b4ec53091a8cb3fc2258ce/obelisk-upgradedeleted
No changes to the content.
migration/be5a7b436cef0ae35cb074700d5f0d00-7c0ab1210424b615251ef57036d316c3/obelisk-handoffdeleted
No changes to the content.
migration/be5a7b436cef0ae35cb074700d5f0d00-7c0ab1210424b615251ef57036d316c3/obelisk-upgradedeleted
No changes to the content.
migration/be615dc4d60c9d8710fbd120857c2fa1-1e376437f069662df26178e4a7873190/obelisk-handoffdeleted
No changes to the content.
migration/be615dc4d60c9d8710fbd120857c2fa1-1e376437f069662df26178e4a7873190/obelisk-upgradedeleted
No changes to the content.
migration/beaa30317dadbef830531237279cbca4-a0f5ac2ff5c6a957e565f898a9fc8bfb/obelisk-handoffdeleted
No changes to the content.
migration/beaa30317dadbef830531237279cbca4-a0f5ac2ff5c6a957e565f898a9fc8bfb/obelisk-upgradedeleted
No changes to the content.
migration/bf22c91488f01ebf503c1786ee805d0c-64ee9e40f4943e0122398e48019f5616/obelisk-handoffdeleted
No changes to the content.
migration/bf22c91488f01ebf503c1786ee805d0c-64ee9e40f4943e0122398e48019f5616/obelisk-upgradedeleted
No changes to the content.
migration/bf3fbc8db3d6fd42a37982dfb5a30b5c-0c6127453069ad707e34ddfedb67e2f9/obelisk-handoffdeleted
No changes to the content.
migration/bf3fbc8db3d6fd42a37982dfb5a30b5c-0c6127453069ad707e34ddfedb67e2f9/obelisk-upgradedeleted
No changes to the content.
migration/bf81caf2a7d528f86acacc1f5d2ffcfa-a5bbc0b9ceab9c3f7ca32a7da8c1f685/obelisk-handoffdeleted
No changes to the content.
migration/bf81caf2a7d528f86acacc1f5d2ffcfa-a5bbc0b9ceab9c3f7ca32a7da8c1f685/obelisk-upgradedeleted
No changes to the content.
migration/c0811b664036c7996fcfd19fee241a10-a2bdbf1985b75442e78e84523c4ced5f/obelisk-handoffdeleted
No changes to the content.
migration/c0811b664036c7996fcfd19fee241a10-a2bdbf1985b75442e78e84523c4ced5f/obelisk-upgradedeleted
No changes to the content.
migration/c0c1452986b8d4c181bb0c6c83c56a2f-bf22c91488f01ebf503c1786ee805d0c/obelisk-handoffdeleted
No changes to the content.
migration/c0c1452986b8d4c181bb0c6c83c56a2f-bf22c91488f01ebf503c1786ee805d0c/obelisk-upgradedeleted
No changes to the content.
migration/c106f9398d5c203a1a296b85c7411bf9-1c2c93819c07f33ad899e39ec6769c3c/obelisk-handoffdeleted
No changes to the content.
migration/c106f9398d5c203a1a296b85c7411bf9-1c2c93819c07f33ad899e39ec6769c3c/obelisk-upgradedeleted
No changes to the content.
migration/c118e1ee09ec8d9aa3edf04e211ae035-749df832c9305e1c6309a794b0c1b201/obelisk-handoffdeleted
No changes to the content.
migration/c118e1ee09ec8d9aa3edf04e211ae035-749df832c9305e1c6309a794b0c1b201/obelisk-upgradedeleted
No changes to the content.
migration/c203adc5fed9bf79f67df43d72a4631a-e6980e47ba847245dfab61fb4d5b8ce5/obelisk-handoffdeleted
No changes to the content.
migration/c203adc5fed9bf79f67df43d72a4631a-e6980e47ba847245dfab61fb4d5b8ce5/obelisk-upgradedeleted
No changes to the content.
migration/c2502429502b46133a749f021d188cf0-93f164bbd887f688fd49bb80afffccd6/obelisk-handoffdeleted
No changes to the content.
migration/c2502429502b46133a749f021d188cf0-93f164bbd887f688fd49bb80afffccd6/obelisk-upgradedeleted
No changes to the content.
migration/c2d4eeb20f2b319a2d9dc5b6b0762f83-01c0ee6c93a3f9f69e097c41169927ac/obelisk-handoffdeleted
No changes to the content.
migration/c2d4eeb20f2b319a2d9dc5b6b0762f83-01c0ee6c93a3f9f69e097c41169927ac/obelisk-upgradedeleted
No changes to the content.
migration/c2d581d48dd821a94d7906ca8f33b504-81223455459db28cdbc990c3d4e6eedd/obelisk-handoffdeleted
No changes to the content.
migration/c2d581d48dd821a94d7906ca8f33b504-81223455459db28cdbc990c3d4e6eedd/obelisk-upgradedeleted
No changes to the content.
migration/c3298d81428117be58196b80853e3c7b-f68462dc88ed7fc451d1c757c040cfee/obelisk-handoffdeleted
No changes to the content.
migration/c3298d81428117be58196b80853e3c7b-f68462dc88ed7fc451d1c757c040cfee/obelisk-upgradedeleted
No changes to the content.
migration/c3a8b70b1290031feb21880914cb081e-c2d581d48dd821a94d7906ca8f33b504/obelisk-handoffdeleted
No changes to the content.
migration/c3a8b70b1290031feb21880914cb081e-c2d581d48dd821a94d7906ca8f33b504/obelisk-upgradedeleted
No changes to the content.
migration/c56de2f95c90def16704f62639246bbc-77a721a8fa97d1f84dd2af622089871b/obelisk-handoffdeleted
No changes to the content.
migration/c56de2f95c90def16704f62639246bbc-77a721a8fa97d1f84dd2af622089871b/obelisk-upgradedeleted
No changes to the content.
migration/c5a306045ad998f906f80748fe18487f-e474bad466cd6e413fba753746eb58ef/obelisk-handoffdeleted
No changes to the content.
migration/c5a306045ad998f906f80748fe18487f-e474bad466cd6e413fba753746eb58ef/obelisk-upgradedeleted
No changes to the content.
migration/c66bc5ba27dec52d144ceb0aa429e449-1b1686b03b41bd840ff46776cec7b33a/obelisk-handoffdeleted
No changes to the content.
migration/c66bc5ba27dec52d144ceb0aa429e449-1b1686b03b41bd840ff46776cec7b33a/obelisk-upgradedeleted
No changes to the content.
migration/c67f206b6d2626eb6d36b00122b52784-3bc53f3a28cb8f403cc41c11a37eec5d/obelisk-handoffdeleted
No changes to the content.
migration/c67f206b6d2626eb6d36b00122b52784-3bc53f3a28cb8f403cc41c11a37eec5d/obelisk-upgradedeleted
No changes to the content.
migration/c6baede3962454713b73acefcc92fe75-a96d491705acc139315264fd340d228f/obelisk-handoffdeleted
No changes to the content.
migration/c6baede3962454713b73acefcc92fe75-a96d491705acc139315264fd340d228f/obelisk-upgradedeleted
No changes to the content.
migration/c6f38304ee53762590c67020f30d2ab4-58391ba73c13d922e8a12116b28caad2/obelisk-handoffdeleted
No changes to the content.
migration/c6f38304ee53762590c67020f30d2ab4-58391ba73c13d922e8a12116b28caad2/obelisk-upgradedeleted
No changes to the content.
migration/c7dbf17de8aebd3043617ea6db790dcc-d35f6eb2d1b066d366c9a89ab26144e1/obelisk-handoffdeleted
No changes to the content.
migration/c7dbf17de8aebd3043617ea6db790dcc-d35f6eb2d1b066d366c9a89ab26144e1/obelisk-upgradedeleted
No changes to the content.
migration/c801cbcf925c0a7b084ef152e3c08f8e-8d5dba70e93ae7e784ea238281842408/obelisk-handoffdeleted
No changes to the content.
migration/c801cbcf925c0a7b084ef152e3c08f8e-8d5dba70e93ae7e784ea238281842408/obelisk-upgradedeleted
No changes to the content.
migration/c93529e579e64263fd91663216fd3fe7-12c8a24c34c2d8441f3181d179c2baab/obelisk-handoffdeleted
No changes to the content.
migration/c93529e579e64263fd91663216fd3fe7-12c8a24c34c2d8441f3181d179c2baab/obelisk-upgradedeleted
No changes to the content.
migration/ca5ee8f372ecb07b09283081f0298733-36cdb1c744c3036c2932f01d5fadd9f5/obelisk-handoffdeleted
No changes to the content.
migration/ca5ee8f372ecb07b09283081f0298733-36cdb1c744c3036c2932f01d5fadd9f5/obelisk-upgradedeleted
No changes to the content.
migration/ca88f98cf9fb63d2feaef7fc19b30eca-962e2bd1ae8d0c233f8da89ecebffe50/obelisk-handoffdeleted
No changes to the content.
migration/ca88f98cf9fb63d2feaef7fc19b30eca-962e2bd1ae8d0c233f8da89ecebffe50/obelisk-upgradedeleted
No changes to the content.
migration/cb2197d0267b52385ee39bf4adcfe475-fbe0c6b69a63f3a44109a2c7526bc577/obelisk-handoffdeleted
No changes to the content.
migration/cb2197d0267b52385ee39bf4adcfe475-fbe0c6b69a63f3a44109a2c7526bc577/obelisk-upgradedeleted
No changes to the content.
migration/cb2d040cc16752b1dc89eecf200ea798-5734398c41e4eb5bb58d933ed2e12041/obelisk-handoffdeleted
No changes to the content.
migration/cb2d040cc16752b1dc89eecf200ea798-5734398c41e4eb5bb58d933ed2e12041/obelisk-upgradedeleted
No changes to the content.
migration/cb98f93880e6dea74014976977d6eb93-a7c7b80a875d1863f027c97eb433b884/obelisk-handoffdeleted
No changes to the content.
migration/cb98f93880e6dea74014976977d6eb93-a7c7b80a875d1863f027c97eb433b884/obelisk-upgradedeleted
No changes to the content.
migration/cba28ee4b736cf8ed43cb342ccaef12e-8e01c7fee83aa74229a77772d8c928f3/obelisk-handoffdeleted
No changes to the content.
migration/cba28ee4b736cf8ed43cb342ccaef12e-8e01c7fee83aa74229a77772d8c928f3/obelisk-upgradedeleted
No changes to the content.
migration/cbe155a3e856fb7eaad0bd18feb408be-4c9372bf9aa6ebed1ea20abf3dbb0075/obelisk-handoffdeleted
No changes to the content.
migration/cbe155a3e856fb7eaad0bd18feb408be-4c9372bf9aa6ebed1ea20abf3dbb0075/obelisk-upgradedeleted
No changes to the content.
migration/cc4307fc88e3486b1c3f9ce07db95808-0fba399e046852d4ecf8e1dad831a2f9/obelisk-handoffdeleted
No changes to the content.
migration/cc4307fc88e3486b1c3f9ce07db95808-0fba399e046852d4ecf8e1dad831a2f9/obelisk-upgradedeleted
No changes to the content.
migration/ccadc106cd03c9c32e77457d3adc77a1-aa8e6712fd46824acdea303068634078/obelisk-handoffdeleted
No changes to the content.
migration/ccadc106cd03c9c32e77457d3adc77a1-aa8e6712fd46824acdea303068634078/obelisk-upgradedeleted
No changes to the content.
migration/cccf4140dc336263489bcf67c8c58f86-d50a30fd9643486c5848399d5ba7f1f1/obelisk-handoffdeleted
No changes to the content.
migration/cccf4140dc336263489bcf67c8c58f86-d50a30fd9643486c5848399d5ba7f1f1/obelisk-upgradedeleted
No changes to the content.
migration/cd38e239c47fb92fabd867b7f86fc99a-7447d29f4712c72458c049cdb9380753/obelisk-handoffdeleted
No changes to the content.
migration/cd38e239c47fb92fabd867b7f86fc99a-7447d29f4712c72458c049cdb9380753/obelisk-upgradedeleted
No changes to the content.
migration/cd5b54d21dd0fb868f48624d41021f47-0fe60df438daa8a2cca5f2b569e361a5/obelisk-handoffdeleted
No changes to the content.
migration/cd5b54d21dd0fb868f48624d41021f47-0fe60df438daa8a2cca5f2b569e361a5/obelisk-upgradedeleted
No changes to the content.
migration/cd86427cc2d5b2e931d7ab03deb19d20-bd8f5fa095c3eb19b87d85247b36f1df/obelisk-handoffdeleted
No changes to the content.
migration/cd86427cc2d5b2e931d7ab03deb19d20-bd8f5fa095c3eb19b87d85247b36f1df/obelisk-upgradedeleted
No changes to the content.
migration/ce7f0d15d71d36d4bcf4fbadcdfa1b58-4db97ca86399c557e5ee0d04d0838acc/obelisk-handoffdeleted
No changes to the content.
migration/ce7f0d15d71d36d4bcf4fbadcdfa1b58-4db97ca86399c557e5ee0d04d0838acc/obelisk-upgradedeleted
No changes to the content.
migration/cffcc6cab6080a35b7bf7c5c7facd6bc-5631293b75143d170b8fca5579e15fee/obelisk-handoffdeleted
No changes to the content.
migration/cffcc6cab6080a35b7bf7c5c7facd6bc-5631293b75143d170b8fca5579e15fee/obelisk-upgradedeleted
No changes to the content.
migration/d125109aa22f485d282f6ceb7cd5936e-9b9d73736773550dde7d36de2498b029/obelisk-handoffdeleted
No changes to the content.
migration/d125109aa22f485d282f6ceb7cd5936e-9b9d73736773550dde7d36de2498b029/obelisk-upgradedeleted
No changes to the content.
migration/d16784e9a2d93db7f953941e3003fa8c-a262678b7d849de5a9732d06199666ae/obelisk-handoffdeleted
No changes to the content.
migration/d16784e9a2d93db7f953941e3003fa8c-a262678b7d849de5a9732d06199666ae/obelisk-upgradedeleted
No changes to the content.
migration/d17b41a4669ac17960559614c830d69a-66f7a274206ad9f6d3c5701e4bcffc9d/obelisk-handoffdeleted
No changes to the content.
migration/d17b41a4669ac17960559614c830d69a-66f7a274206ad9f6d3c5701e4bcffc9d/obelisk-upgradedeleted
No changes to the content.
migration/d1b3f5f5375558bf91d55c88547784b9-c0811b664036c7996fcfd19fee241a10/obelisk-handoffdeleted
No changes to the content.
migration/d1b3f5f5375558bf91d55c88547784b9-c0811b664036c7996fcfd19fee241a10/obelisk-upgradedeleted
No changes to the content.
migration/d207ab99328b8ece5fb27fa1f4dbf9f6-e6a85005bd7e5d343bc23e17bfc345f6/obelisk-handoffdeleted
No changes to the content.
migration/d207ab99328b8ece5fb27fa1f4dbf9f6-e6a85005bd7e5d343bc23e17bfc345f6/obelisk-upgradedeleted
No changes to the content.
migration/d2d86ce0ca16b143b49374302a9e9e2f-84f4d5c5491abb855d8dbe3acf3bc8e6/obelisk-handoffdeleted
No changes to the content.
migration/d2d86ce0ca16b143b49374302a9e9e2f-84f4d5c5491abb855d8dbe3acf3bc8e6/obelisk-upgradedeleted
No changes to the content.
migration/d327ceb69d24e40dc11792840454cff9-de469e6488ddf192f2104ec0a030daf7/obelisk-handoffdeleted
No changes to the content.
migration/d327ceb69d24e40dc11792840454cff9-de469e6488ddf192f2104ec0a030daf7/obelisk-upgradedeleted
No changes to the content.
migration/d35f6eb2d1b066d366c9a89ab26144e1-03b9747848d7f3e995b118f776ef96c7/obelisk-handoffdeleted
No changes to the content.
migration/d35f6eb2d1b066d366c9a89ab26144e1-03b9747848d7f3e995b118f776ef96c7/obelisk-upgradedeleted
No changes to the content.
migration/d37d70fe5d7d11e68b59ce12022281c9-5f0d3f7480d67df7deebdb880726b356/obelisk-handoffdeleted
No changes to the content.
migration/d37d70fe5d7d11e68b59ce12022281c9-5f0d3f7480d67df7deebdb880726b356/obelisk-upgradedeleted
No changes to the content.
migration/d40e0e3051a76c4c198cc11c2e8e4b7c-1859cc62bb2f89f528bb2aa170c36e84/obelisk-handoffdeleted
No changes to the content.
migration/d40e0e3051a76c4c198cc11c2e8e4b7c-1859cc62bb2f89f528bb2aa170c36e84/obelisk-upgradedeleted
No changes to the content.
migration/d50a30fd9643486c5848399d5ba7f1f1-1f5b6e2a19c87d3820b953f942ab4a27/obelisk-handoffdeleted
No changes to the content.
migration/d50a30fd9643486c5848399d5ba7f1f1-1f5b6e2a19c87d3820b953f942ab4a27/obelisk-upgradedeleted
No changes to the content.
migration/d532356dfb65a4c8a39452d2ebca2516-bf81caf2a7d528f86acacc1f5d2ffcfa/obelisk-handoffdeleted
No changes to the content.
migration/d532356dfb65a4c8a39452d2ebca2516-bf81caf2a7d528f86acacc1f5d2ffcfa/obelisk-upgradedeleted
No changes to the content.
migration/d5ba6f13296205e5bd88ca2756107df0-26a2491fc8a9658751c1511c777a67bd/obelisk-handoffdeleted
No changes to the content.
migration/d5ba6f13296205e5bd88ca2756107df0-26a2491fc8a9658751c1511c777a67bd/obelisk-upgradedeleted
No changes to the content.
migration/d62d6d443d9c2261b7e09664398aa005-fcc617e973168e1210379a6afe7171be/obelisk-handoffdeleted
No changes to the content.
migration/d62d6d443d9c2261b7e09664398aa005-fcc617e973168e1210379a6afe7171be/obelisk-upgradedeleted
No changes to the content.
migration/d6a3ea5f7eb3c95f5e5ea09fb1330270-bc7688ff47218c0e13d02d917b03caa0/obelisk-handoffdeleted
No changes to the content.
migration/d6a3ea5f7eb3c95f5e5ea09fb1330270-bc7688ff47218c0e13d02d917b03caa0/obelisk-upgradedeleted
No changes to the content.
migration/d6b34eba6ed4f89875a6615fe2c41ec2-3daecb03985f83d8af466a9e0541782b/obelisk-handoffdeleted
No changes to the content.
migration/d6b34eba6ed4f89875a6615fe2c41ec2-3daecb03985f83d8af466a9e0541782b/obelisk-upgradedeleted
No changes to the content.
migration/d6c090699acd25fc60213ff4bd9eebcf-0298e61f6a03e553df08dcef03e27bd1/obelisk-handoffdeleted
No changes to the content.
migration/d6c090699acd25fc60213ff4bd9eebcf-0298e61f6a03e553df08dcef03e27bd1/obelisk-upgradedeleted
No changes to the content.
migration/d6cacd7f4fab95c4b6aa2d6c1a4ad2a0-4d6197d8166de78f882376102e36300b/obelisk-handoffdeleted
No changes to the content.
migration/d6cacd7f4fab95c4b6aa2d6c1a4ad2a0-4d6197d8166de78f882376102e36300b/obelisk-upgradedeleted
No changes to the content.
migration/d747c3d0620b2034aca44265dd1c8c86-eeb970434a53f4883c9f0255db555581/obelisk-handoffdeleted
No changes to the content.
migration/d747c3d0620b2034aca44265dd1c8c86-eeb970434a53f4883c9f0255db555581/obelisk-upgradedeleted
No changes to the content.
migration/d8adb57b2f2266e128ebb6f6d7e65920-ccadc106cd03c9c32e77457d3adc77a1/obelisk-handoffdeleted
No changes to the content.
migration/d8adb57b2f2266e128ebb6f6d7e65920-ccadc106cd03c9c32e77457d3adc77a1/obelisk-upgradedeleted
No changes to the content.
migration/da23605ee4058c8474687e74a3999354-dfd7dbceea141c60bbfca962d50c1c06/obelisk-handoffdeleted
No changes to the content.
migration/da23605ee4058c8474687e74a3999354-dfd7dbceea141c60bbfca962d50c1c06/obelisk-upgradedeleted
No changes to the content.
migration/db327f87e60d4e59bdbfd482e5abe985-eb99c1a66237ba99cd1f6d244cafb9cc/obelisk-handoffdeleted
No changes to the content.
migration/db327f87e60d4e59bdbfd482e5abe985-eb99c1a66237ba99cd1f6d244cafb9cc/obelisk-upgradedeleted
No changes to the content.
migration/dc95f39fb27634ccbca7318ff2065608-0fb3a912a8aaf5ef6f734a25f0bce7e2/obelisk-handoffdeleted
No changes to the content.
migration/dc95f39fb27634ccbca7318ff2065608-0fb3a912a8aaf5ef6f734a25f0bce7e2/obelisk-upgradedeleted
No changes to the content.
migration/dd6ca52a58ea6cda7b3eaa2e87bb13d9-a6d50c7e756dfd1e3ae891111b81a1ae/obelisk-handoffdeleted
No changes to the content.
migration/dd6ca52a58ea6cda7b3eaa2e87bb13d9-a6d50c7e756dfd1e3ae891111b81a1ae/obelisk-upgradedeleted
No changes to the content.
migration/ddaa8e0e42a1ef00154d580a390c9f17-53d29061537ddaf7530aef88624ab266/obelisk-handoffdeleted
No changes to the content.
migration/ddaa8e0e42a1ef00154d580a390c9f17-53d29061537ddaf7530aef88624ab266/obelisk-upgradedeleted
No changes to the content.
migration/de469e6488ddf192f2104ec0a030daf7-3da7d4a3b507d18097a90becf4dde9aa/obelisk-handoffdeleted
No changes to the content.
migration/de469e6488ddf192f2104ec0a030daf7-3da7d4a3b507d18097a90becf4dde9aa/obelisk-upgradedeleted
No changes to the content.
migration/df71cd82e801ca701bf4bc44b80b6d50-f423ecd4d096de9dca37a67b8b4143eb/obelisk-handoffdeleted
No changes to the content.
migration/df71cd82e801ca701bf4bc44b80b6d50-f423ecd4d096de9dca37a67b8b4143eb/obelisk-upgradedeleted
No changes to the content.
migration/dfd7dbceea141c60bbfca962d50c1c06-030ed18dacf3571cbb9e3e7d9d99627b/obelisk-handoffdeleted
No changes to the content.
migration/dfd7dbceea141c60bbfca962d50c1c06-030ed18dacf3571cbb9e3e7d9d99627b/obelisk-upgradedeleted
No changes to the content.
migration/e01cc01684deaf4c75ad5d65270bf3d5-c7dbf17de8aebd3043617ea6db790dcc/obelisk-handoffdeleted
No changes to the content.
migration/e01cc01684deaf4c75ad5d65270bf3d5-c7dbf17de8aebd3043617ea6db790dcc/obelisk-upgradedeleted
No changes to the content.
migration/e1ef432db54d9a6daa9bdeeb543262ae-2ba356b187db8db13b8aa40f43ca025f/obelisk-handoffdeleted
No changes to the content.
migration/e1ef432db54d9a6daa9bdeeb543262ae-2ba356b187db8db13b8aa40f43ca025f/obelisk-upgradedeleted
No changes to the content.
migration/e22c51145e08d4a089003460ae80a7f9-42357310c09e345f9360259c6c4102f2/obelisk-handoffdeleted
No changes to the content.
migration/e22c51145e08d4a089003460ae80a7f9-42357310c09e345f9360259c6c4102f2/obelisk-upgradedeleted
No changes to the content.
migration/e24a771ee59f24e45afc0a27307f2070-2eb907820012f77e60350430d89631fe/obelisk-handoffdeleted
No changes to the content.
migration/e24a771ee59f24e45afc0a27307f2070-2eb907820012f77e60350430d89631fe/obelisk-upgradedeleted
No changes to the content.
migration/e2706f337218a12a3bdddd18fa3f4cfd-475f9a0d63e84e9cf13b8be3986cb603/obelisk-handoffdeleted
No changes to the content.
migration/e2706f337218a12a3bdddd18fa3f4cfd-475f9a0d63e84e9cf13b8be3986cb603/obelisk-upgradedeleted
No changes to the content.
migration/e2b2d878b0ba6eb653b194523bf0a0e0-5f307639ccf6a64309166bfe58037397/obelisk-handoffdeleted
No changes to the content.
migration/e2b2d878b0ba6eb653b194523bf0a0e0-5f307639ccf6a64309166bfe58037397/obelisk-upgradedeleted
No changes to the content.
migration/e2be519915794ef130249f2be7640382-455279b6974b96a673613cd0ccc8ed54/obelisk-handoffdeleted
No changes to the content.
migration/e2be519915794ef130249f2be7640382-455279b6974b96a673613cd0ccc8ed54/obelisk-upgradedeleted
No changes to the content.
migration/e323ce1352e512109f1609276fb509b4-2c1521e5a5be64e6d28a9fdae950cd76/obelisk-handoffdeleted
No changes to the content.
migration/e323ce1352e512109f1609276fb509b4-2c1521e5a5be64e6d28a9fdae950cd76/obelisk-upgradedeleted
No changes to the content.
migration/e327773e1525eaa1eb2112dff8f41b26-f595b01939b4c87b7c146ea9ff331b39/obelisk-handoffdeleted
No changes to the content.
migration/e327773e1525eaa1eb2112dff8f41b26-f595b01939b4c87b7c146ea9ff331b39/obelisk-upgradedeleted
No changes to the content.
migration/e3b3014d7e0dc983fe118d32546654e5-063665b78b6705e7de952f73fa9797bf/obelisk-handoffdeleted
No changes to the content.
migration/e3b3014d7e0dc983fe118d32546654e5-063665b78b6705e7de952f73fa9797bf/obelisk-upgradedeleted
No changes to the content.
migration/e4051219d89b3c9a8350fe824ad96a82-166c5f8e4a0f1dfd227b075a96237386/obelisk-handoffdeleted
No changes to the content.
migration/e4051219d89b3c9a8350fe824ad96a82-166c5f8e4a0f1dfd227b075a96237386/obelisk-upgradedeleted
No changes to the content.
migration/e4513b485b6ba8b7f4bd34b12458ff0c-3c80eccfe80d0abd36b07bb11e69fc7a/obelisk-handoffdeleted
No changes to the content.
migration/e4513b485b6ba8b7f4bd34b12458ff0c-3c80eccfe80d0abd36b07bb11e69fc7a/obelisk-upgradedeleted
No changes to the content.
migration/e474bad466cd6e413fba753746eb58ef-f19b3699616f3b1de3a277f9cba617c7/obelisk-handoffdeleted
No changes to the content.
migration/e474bad466cd6e413fba753746eb58ef-f19b3699616f3b1de3a277f9cba617c7/obelisk-upgradedeleted
No changes to the content.
migration/e4b89dd259f3831bc60b56147b3586a6-98da197f133bca81e533ab5ffbf4c82d/obelisk-handoffdeleted
No changes to the content.
migration/e4b89dd259f3831bc60b56147b3586a6-98da197f133bca81e533ab5ffbf4c82d/obelisk-upgradedeleted
No changes to the content.
migration/e609d945b642fd9d4ce99931e3699db7-85c2c4fb8472d50eaa97aed0bdc9b142/obelisk-handoffdeleted
No changes to the content.
migration/e609d945b642fd9d4ce99931e3699db7-85c2c4fb8472d50eaa97aed0bdc9b142/obelisk-upgradedeleted
No changes to the content.
migration/e6980e47ba847245dfab61fb4d5b8ce5-58f9d23d2cede2081dc6f6cfa2283f60/obelisk-handoffdeleted
No changes to the content.
migration/e6980e47ba847245dfab61fb4d5b8ce5-58f9d23d2cede2081dc6f6cfa2283f60/obelisk-upgradedeleted
No changes to the content.
migration/e6a85005bd7e5d343bc23e17bfc345f6-98f9e0bbd21e36b0f4daa440d11e7177/obelisk-handoffdeleted
No changes to the content.
migration/e6a85005bd7e5d343bc23e17bfc345f6-98f9e0bbd21e36b0f4daa440d11e7177/obelisk-upgradedeleted
No changes to the content.
migration/e7288bb723a4e5b7139ac67842963287-7b75ffdcd86b5a330d9c325ad5767393/obelisk-handoffdeleted
No changes to the content.
migration/e7288bb723a4e5b7139ac67842963287-7b75ffdcd86b5a330d9c325ad5767393/obelisk-upgradedeleted
No changes to the content.
migration/e7385c9eae2b807a483b73be4295b207-fb02559b6f723d599e12931a81be3a1b/obelisk-handoffdeleted
No changes to the content.
migration/e7385c9eae2b807a483b73be4295b207-fb02559b6f723d599e12931a81be3a1b/obelisk-upgradedeleted
No changes to the content.
migration/e7667778f2ab3055aa3ccc68443d14df-7adece557941a7d7ac7c150f77f758be/obelisk-handoffdeleted
No changes to the content.
migration/e7667778f2ab3055aa3ccc68443d14df-7adece557941a7d7ac7c150f77f758be/obelisk-upgradedeleted
No changes to the content.
migration/e78ec85bec14f4784faeef4d8d3e4d0a-e7667778f2ab3055aa3ccc68443d14df/obelisk-handoffdeleted
No changes to the content.
migration/e78ec85bec14f4784faeef4d8d3e4d0a-e7667778f2ab3055aa3ccc68443d14df/obelisk-upgradedeleted
No changes to the content.
migration/e7b17aa124e17c357cead8081a58f089-ac5e28caddd6832d0bf1f7445a4a6a28/obelisk-handoffdeleted
No changes to the content.
migration/e7b17aa124e17c357cead8081a58f089-ac5e28caddd6832d0bf1f7445a4a6a28/obelisk-upgradedeleted
No changes to the content.
migration/e7b566495114e160f1f4d722b7ed8174-7cf814f7404638f1c1be662a24d7cfea/obelisk-handoffdeleted
No changes to the content.
migration/e7b566495114e160f1f4d722b7ed8174-7cf814f7404638f1c1be662a24d7cfea/obelisk-upgradedeleted
No changes to the content.
migration/e92786eaf56c32fd6b452c4a841d6317-f24a7fb6e3261c4919ea2a2fee83ed6b/obelisk-handoffdeleted
No changes to the content.
migration/e92786eaf56c32fd6b452c4a841d6317-f24a7fb6e3261c4919ea2a2fee83ed6b/obelisk-upgradedeleted
No changes to the content.
migration/e9ec84bfe7099b713c0fda32308f5815-f0a064ca5f709233204168c136b99a7e/obelisk-handoffdeleted
No changes to the content.
migration/e9ec84bfe7099b713c0fda32308f5815-f0a064ca5f709233204168c136b99a7e/obelisk-upgradedeleted
No changes to the content.
migration/eb99c1a66237ba99cd1f6d244cafb9cc-da23605ee4058c8474687e74a3999354/obelisk-handoffdeleted
No changes to the content.
migration/eb99c1a66237ba99cd1f6d244cafb9cc-da23605ee4058c8474687e74a3999354/obelisk-upgradedeleted
No changes to the content.
migration/ebb95c5864d1d1d2f78fbf7cc8235dac-ba4829dc61dcc12bcafd8de5fc8a76dc/obelisk-handoffdeleted
No changes to the content.
migration/ebb95c5864d1d1d2f78fbf7cc8235dac-ba4829dc61dcc12bcafd8de5fc8a76dc/obelisk-upgradedeleted
No changes to the content.
migration/ec11d10a6131abca9222a8f8026fb5e4-f3d494ffee7091cd588bbdd2fd9bcdf9/obelisk-handoffdeleted
No changes to the content.
migration/ec11d10a6131abca9222a8f8026fb5e4-f3d494ffee7091cd588bbdd2fd9bcdf9/obelisk-upgradedeleted
No changes to the content.
migration/ec94619fa3f25db1ca84d179e47db1ca-23af4d9671962484de53f537a0626d83/obelisk-handoffdeleted
No changes to the content.
migration/ec94619fa3f25db1ca84d179e47db1ca-23af4d9671962484de53f537a0626d83/obelisk-upgradedeleted
No changes to the content.
migration/ed95a99cdde4adc90c6a8e2de82410eb-1c4fc23cbf5653613c6060668e065f37/obelisk-handoffdeleted
No changes to the content.
migration/ed95a99cdde4adc90c6a8e2de82410eb-1c4fc23cbf5653613c6060668e065f37/obelisk-upgradedeleted
No changes to the content.
migration/ee3dccc89ea6fdaaf9c1146b92861e90-f3eac05465851232f8174a7a347d1c4b/obelisk-handoffdeleted
No changes to the content.
migration/ee3dccc89ea6fdaaf9c1146b92861e90-f3eac05465851232f8174a7a347d1c4b/obelisk-upgradedeleted
No changes to the content.
migration/eeb970434a53f4883c9f0255db555581-a2b33f8dc1f90b8dddce942b174be5b8/obelisk-handoffdeleted
No changes to the content.
migration/eeb970434a53f4883c9f0255db555581-a2b33f8dc1f90b8dddce942b174be5b8/obelisk-upgradedeleted
No changes to the content.
migration/ef33c06500054e09c97eee9e9c55485a-367616bd36eda757f251a5e8e9096acc/obelisk-handoffdeleted
No changes to the content.
migration/ef33c06500054e09c97eee9e9c55485a-367616bd36eda757f251a5e8e9096acc/obelisk-upgradedeleted
No changes to the content.
migration/ef6aebc8cba2af6c4f930c981b06e8ac-d17b41a4669ac17960559614c830d69a/obelisk-handoffdeleted
No changes to the content.
migration/ef6aebc8cba2af6c4f930c981b06e8ac-d17b41a4669ac17960559614c830d69a/obelisk-upgradedeleted
No changes to the content.
migration/f0a064ca5f709233204168c136b99a7e-ef6aebc8cba2af6c4f930c981b06e8ac/obelisk-handoffdeleted
No changes to the content.
migration/f0a064ca5f709233204168c136b99a7e-ef6aebc8cba2af6c4f930c981b06e8ac/obelisk-upgradedeleted
No changes to the content.
migration/f15c9c2f894c8cc4fac07e2cdef47180-94252585266fa745a91733888e2f50b7/obelisk-handoffdeleted
No changes to the content.
migration/f15c9c2f894c8cc4fac07e2cdef47180-94252585266fa745a91733888e2f50b7/obelisk-upgradedeleted
No changes to the content.
migration/f19b3699616f3b1de3a277f9cba617c7-4d85ee8cdb0db20a5662b09567a2bbe7/obelisk-handoffdeleted
No changes to the content.
migration/f19b3699616f3b1de3a277f9cba617c7-4d85ee8cdb0db20a5662b09567a2bbe7/obelisk-upgradedeleted
No changes to the content.
migration/f24a7fb6e3261c4919ea2a2fee83ed6b-f913f01e90549c56a8b05f8100cfa21d/obelisk-handoffdeleted
No changes to the content.
migration/f24a7fb6e3261c4919ea2a2fee83ed6b-f913f01e90549c56a8b05f8100cfa21d/obelisk-upgradedeleted
No changes to the content.
migration/f2a9ba4a93c3a04acbee2211bca9e27a-ec94619fa3f25db1ca84d179e47db1ca/obelisk-handoffdeleted
No changes to the content.
migration/f2a9ba4a93c3a04acbee2211bca9e27a-ec94619fa3f25db1ca84d179e47db1ca/obelisk-upgradedeleted
No changes to the content.
migration/f391c6a74ee14217ce4565c278fceed6-e7288bb723a4e5b7139ac67842963287/obelisk-handoffdeleted
No changes to the content.
migration/f391c6a74ee14217ce4565c278fceed6-e7288bb723a4e5b7139ac67842963287/obelisk-upgradedeleted
No changes to the content.
migration/f3d494ffee7091cd588bbdd2fd9bcdf9-b68a785fbf27a63334ef1d1fe82b2dac/obelisk-handoffdeleted
No changes to the content.
migration/f3d494ffee7091cd588bbdd2fd9bcdf9-b68a785fbf27a63334ef1d1fe82b2dac/obelisk-upgradedeleted
No changes to the content.
migration/f3eac05465851232f8174a7a347d1c4b-1629d0d70e360df6b2280fac36d21e8a/obelisk-handoffdeleted
No changes to the content.
migration/f3eac05465851232f8174a7a347d1c4b-1629d0d70e360df6b2280fac36d21e8a/obelisk-upgradedeleted
No changes to the content.
migration/f3ec62d09836804e39fad9d814137845-ef33c06500054e09c97eee9e9c55485a/obelisk-handoffdeleted
No changes to the content.
migration/f3ec62d09836804e39fad9d814137845-ef33c06500054e09c97eee9e9c55485a/obelisk-upgradedeleted
No changes to the content.
migration/f41b690c74938e347cf042cee2d4fc72-7fc381538805adac19c54b73ea118601/obelisk-handoffdeleted
No changes to the content.
migration/f41b690c74938e347cf042cee2d4fc72-7fc381538805adac19c54b73ea118601/obelisk-upgradedeleted
No changes to the content.
migration/f423ecd4d096de9dca37a67b8b4143eb-469a31d20d69da72e6a3a3ea2bb02f9d/obelisk-handoffdeleted
No changes to the content.
migration/f423ecd4d096de9dca37a67b8b4143eb-469a31d20d69da72e6a3a3ea2bb02f9d/obelisk-upgradedeleted
No changes to the content.
migration/f595b01939b4c87b7c146ea9ff331b39-4da182e21be35feeee484dc85be7a075/obelisk-handoffdeleted
No changes to the content.
migration/f595b01939b4c87b7c146ea9ff331b39-4da182e21be35feeee484dc85be7a075/obelisk-upgradedeleted
No changes to the content.
migration/f68462dc88ed7fc451d1c757c040cfee-589eb89cdb09655c5edde4cd2a4deb80/obelisk-handoffdeleted
No changes to the content.
migration/f68462dc88ed7fc451d1c757c040cfee-589eb89cdb09655c5edde4cd2a4deb80/obelisk-upgradedeleted
No changes to the content.
migration/f790ac9400501511b4ee045e22bc5fe1-a826f01311fe00ef5cf87568832605d3/obelisk-handoffdeleted
No changes to the content.
migration/f790ac9400501511b4ee045e22bc5fe1-a826f01311fe00ef5cf87568832605d3/obelisk-upgradedeleted
No changes to the content.
migration/f8e51a9e8ac6598f7c073b09e4ba09b5-ff57aebc7325bd7e02b436fec79e799c/obelisk-handoffdeleted
No changes to the content.
migration/f8e51a9e8ac6598f7c073b09e4ba09b5-ff57aebc7325bd7e02b436fec79e799c/obelisk-upgradedeleted
No changes to the content.
migration/f8eee9431c8b7a767d96da0a8cfae95d-9e05cc6b81c6380ba0ac59bad1021cac/obelisk-handoffdeleted
No changes to the content.
migration/f8eee9431c8b7a767d96da0a8cfae95d-9e05cc6b81c6380ba0ac59bad1021cac/obelisk-upgradedeleted
No changes to the content.
migration/f913f01e90549c56a8b05f8100cfa21d-001efbbe866b66eebc6ee1ea0a906f2d/obelisk-handoffdeleted
No changes to the content.
migration/f913f01e90549c56a8b05f8100cfa21d-001efbbe866b66eebc6ee1ea0a906f2d/obelisk-upgradedeleted
No changes to the content.
migration/f9716ad47c84e0b7ac7d426e8ad059f3-ec11d10a6131abca9222a8f8026fb5e4/obelisk-handoffdeleted
No changes to the content.
migration/f9716ad47c84e0b7ac7d426e8ad059f3-ec11d10a6131abca9222a8f8026fb5e4/obelisk-upgradedeleted
No changes to the content.
migration/f98b82f5d142ce83733a3f18bdacb138-35acc1e0c4d9c02d60abd116f3df84ee/obelisk-handoffdeleted
No changes to the content.
migration/f98b82f5d142ce83733a3f18bdacb138-35acc1e0c4d9c02d60abd116f3df84ee/obelisk-upgradedeleted
No changes to the content.
migration/f9ad863c0bebc103f8b81afdf82e6293-c6f38304ee53762590c67020f30d2ab4/obelisk-handoffdeleted
No changes to the content.
migration/f9ad863c0bebc103f8b81afdf82e6293-c6f38304ee53762590c67020f30d2ab4/obelisk-upgradedeleted
No changes to the content.
migration/fa18f7522903a21b615dbee24c26bfbe-0535e06dd0d61f3e6970b491a17cf1f8/obelisk-handoffdeleted
No changes to the content.
migration/fa18f7522903a21b615dbee24c26bfbe-0535e06dd0d61f3e6970b491a17cf1f8/obelisk-upgradedeleted
No changes to the content.
migration/fb02559b6f723d599e12931a81be3a1b-71a47d4d6856c1956c0d1c9de9af231f/obelisk-handoffdeleted
No changes to the content.
migration/fb02559b6f723d599e12931a81be3a1b-71a47d4d6856c1956c0d1c9de9af231f/obelisk-upgradedeleted
No changes to the content.
migration/fb374b0721716a1e849e64daf6da73c4-f8e51a9e8ac6598f7c073b09e4ba09b5/obelisk-handoffdeleted
No changes to the content.
migration/fb374b0721716a1e849e64daf6da73c4-f8e51a9e8ac6598f7c073b09e4ba09b5/obelisk-upgradedeleted
No changes to the content.
migration/fb5110e527cf77c568bcae7d435ee035-53fdf819333b86dfb485bf16a8f28db2/obelisk-handoffdeleted
No changes to the content.
migration/fb5110e527cf77c568bcae7d435ee035-53fdf819333b86dfb485bf16a8f28db2/obelisk-upgradedeleted
No changes to the content.
migration/fb81153791e49cd00850e91ff7418018-9b33a49f0c978e27b752fa457aca97cc/obelisk-handoffdeleted
No changes to the content.
migration/fb81153791e49cd00850e91ff7418018-9b33a49f0c978e27b752fa457aca97cc/obelisk-upgradedeleted
No changes to the content.
migration/fbb3eb3209281031dc5183d289eb4e75-8c7718f94e2676c957fe844b7dc2637c/obelisk-handoffdeleted
No changes to the content.
migration/fbb3eb3209281031dc5183d289eb4e75-8c7718f94e2676c957fe844b7dc2637c/obelisk-upgradedeleted
No changes to the content.
migration/fbe0c6b69a63f3a44109a2c7526bc577-c3a8b70b1290031feb21880914cb081e/obelisk-handoffdeleted
No changes to the content.
migration/fbe0c6b69a63f3a44109a2c7526bc577-c3a8b70b1290031feb21880914cb081e/obelisk-upgradedeleted
No changes to the content.
migration/fc42c5fc24031fc6a8836a10cfb45143-d125109aa22f485d282f6ceb7cd5936e/obelisk-handoffdeleted
No changes to the content.
migration/fc42c5fc24031fc6a8836a10cfb45143-d125109aa22f485d282f6ceb7cd5936e/obelisk-upgradedeleted
No changes to the content.
migration/fca48edfdaa31b036176b97b04384682-2df092178e167b474dd08dfa46ec3a49/obelisk-handoffdeleted
No changes to the content.
migration/fca48edfdaa31b036176b97b04384682-2df092178e167b474dd08dfa46ec3a49/obelisk-upgradedeleted
No changes to the content.
migration/fcc617e973168e1210379a6afe7171be-ed95a99cdde4adc90c6a8e2de82410eb/obelisk-handoffdeleted
No changes to the content.
migration/fcc617e973168e1210379a6afe7171be-ed95a99cdde4adc90c6a8e2de82410eb/obelisk-upgradedeleted
No changes to the content.
migration/ff1105290f89350bc9deb6eb907e0a53-0c991bc3c06801f72df48486ee78e350/obelisk-handoffdeleted
No changes to the content.
migration/ff1105290f89350bc9deb6eb907e0a53-0c991bc3c06801f72df48486ee78e350/obelisk-upgradedeleted
No changes to the content.
migration/ff57aebc7325bd7e02b436fec79e799c-9f71fc9d2ed805fecbc8c4a3aae5685b/obelisk-handoffdeleted
No changes to the content.
migration/ff57aebc7325bd7e02b436fec79e799c-9f71fc9d2ed805fecbc8c4a3aae5685b/obelisk-upgradedeleted
No changes to the content.
migration/ffa62158ed6fdece012980e4ad25e6ac-959ae2925bcd2b5beff631a8e7aeaf00/obelisk-handoffdeleted
No changes to the content.
migration/ffa62158ed6fdece012980e4ad25e6ac-959ae2925bcd2b5beff631a8e7aeaf00/obelisk-upgradedeleted
No changes to the content.
@@ -1,45 +1,80 @@
1{ local-self ? import ./. {}
1{ local-self ? import ./. {}
2−, local-pkgs ? local-self.nixpkgs
5−with local-pkgs.lib;
4+let
6−
5+ inherit (local-self.nixpkgs) lib runCommand nix;
7−genAttrs [ "x86_64-linux" "x86_64-darwin" ] (system: {
6+
8− inherit (import ./. { inherit system; }) command;
7+ cacheBuildSystems = [ "x86_64-linux" "x86_64-darwin" ];
9− built-skeleton = (import ./skeleton { inherit system; }).all;
8+
10− tests = {
9+ obeliskPackagesCommon = [
11− #TODO: Doesn't work; see discussion in https://www.pivotaltracker.com/story/show/157265140
10+ "obelisk-frontend"
12− # ob-init = runCommand "ob-init" {
11+ "obelisk-route"
13− # nativeBuildInputs = [
12+ "obelisk-executable-config"
16− # ];
15+ obeliskPackagesBackend = obeliskPackagesCommon ++ [
17− # } ''
16+ "obelisk-asset-manifest"
18− # # mkdir $out
17+ "obelisk-asset-serve-snap"
19− # # cd $out
18+ "obelisk-backend"
20− # # ob init --symlink=${self.path}
19+ "obelisk-cliapp"
21− #'';
20+ "obelisk-command"
22−
21+ "obelisk-executable-config-inject"
23− #TODO: Re-enable this
22+ "obelisk-frontend"
24− #verify-migration = runCommand "verify-migration" {
23+ "obelisk-run"
25− # nativeBuildInputs = [
24+ "obelisk-route"
26− # self.command
25+ "obelisk-selftest"
27− # nix # obelisk uses `nix-hash`
26+ "obelisk-snap-extras"
30− # set -e
29+ pnameToAttrs = pkgsSet: pnames:
31− # # Fix permissions so `removePathForcibly` works on copied-to-tmp paths
30+ lib.listToAttrs (map
32− # cp -a ${self.pathGit} $TMPDIR/obelisk
31+ (name: { inherit name; value = pkgsSet.${name}; })
33− # cd $TMPDIR/obelisk
32+ pnames);
35− #
34+ concatDepends = let
36− # (set -x;
35+ extractDeps = x: (x.override {
37− # ob internal hash;
36+ mkDerivation = drv: {
38− # ob internal verify-migration;
37+ out = builtins.concatLists [
39− # )
38+ (drv.buildDepends or [])
40− #
39+ (drv.libraryHaskellDepends or [])
41− # mkdir -p $out
40+ (drv.executableHaskellDepends or [])
42− # touch $out/done
41+ ];
45−})
44+ in pkgAttrs: builtins.concatLists (map extractDeps (builtins.attrValues pkgAttrs));
46+ perPlatform = lib.genAttrs cacheBuildSystems (system: let
47+ obelisk = import ./. { inherit system; };
48+ reflex-platform = obelisk.reflex-platform;
50+ obelisk.haskellPackageSets.ghc
51+ obeliskPackagesBackend;
53+ obelisk.haskellPackageSets.ghcjs
54+ obeliskPackagesCommon;
55+ cachePackages = builtins.concatLists [
56+ (builtins.attrValues ghc)
57+ (builtins.attrValues ghcjs)
59+ (concatDepends ghcjs)
61+ command = local-self.command;
62+ serverExeSkeleton = (import ./skeleton {}).exe;
63+ builtSkeleton = (import ./skeleton {}).all;
68+ serverExeSkeleton builtSkeleton;
69+ cache = reflex-platform.pinBuildInputs
72+ [command serverExeSkeleton builtSkeleton];
75+ metaCache = local-self.pinBuildInputs
77+ (map (a: a.cache) (builtins.attrValues perPlatform))
80+in perPlatform // { inherit metaCache; }