chore: Remove buildGo and supporting infrastructure
It's no longer in use. Change-Id: Ie84ab1d9c75be79a25ee976575660ee1484e17bb Reviewed-on: https://cl.snix.dev/c/snix/+/30187 Tested-by: besadii Reviewed-by: Florian Klink <flokli@flokli.de>
This commit is contained in:
parent
d99819280a
commit
0959faf056
52 changed files with 0 additions and 1520 deletions
|
|
@ -1,2 +0,0 @@
|
||||||
Subdirectories of this folder should not be imported since they are
|
|
||||||
internal to buildGo.nix and incompatible with readTree.
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
buildGo.nix
|
|
||||||
===========
|
|
||||||
|
|
||||||
This is an alternative [Nix][] build system for [Go][]. It supports building Go
|
|
||||||
libraries and programs.
|
|
||||||
|
|
||||||
*Note:* This will probably end up being folded into [Nixery][].
|
|
||||||
|
|
||||||
## Background
|
|
||||||
|
|
||||||
Most language-specific Nix tooling outsources the build to existing
|
|
||||||
language-specific build tooling, which essentially means that Nix ends up being
|
|
||||||
a wrapper around all sorts of external build systems.
|
|
||||||
|
|
||||||
However, systems like [Bazel][] take an alternative approach in which the
|
|
||||||
compiler is invoked directly and the composition of programs and libraries stays
|
|
||||||
within a single homogeneous build system.
|
|
||||||
|
|
||||||
Users don't need to learn per-language build systems and especially for
|
|
||||||
companies with large monorepo-setups ([like Google][]) this has huge
|
|
||||||
productivity impact.
|
|
||||||
|
|
||||||
This project is an attempt to prove that Nix can be used in a similar style to
|
|
||||||
build software directly, rather than shelling out to other build systems.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Given a program layout like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
.
|
|
||||||
├── lib <-- some library component
|
|
||||||
│ ├── bar.go
|
|
||||||
│ └── foo.go
|
|
||||||
├── main.go <-- program implementation
|
|
||||||
└── default.nix <-- build instructions
|
|
||||||
```
|
|
||||||
|
|
||||||
The contents of `default.nix` could look like this:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ buildGo }:
|
|
||||||
|
|
||||||
let
|
|
||||||
lib = buildGo.package {
|
|
||||||
name = "somelib";
|
|
||||||
srcs = [
|
|
||||||
./lib/bar.go
|
|
||||||
./lib/foo.go
|
|
||||||
];
|
|
||||||
};
|
|
||||||
in buildGo.program {
|
|
||||||
name = "my-program";
|
|
||||||
deps = [ lib ];
|
|
||||||
|
|
||||||
srcs = [
|
|
||||||
./main.go
|
|
||||||
];
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
(If you don't know how to read Nix, check out [nix-1p][])
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
`buildGo` exposes five different functions:
|
|
||||||
|
|
||||||
* `buildGo.program`: Build a Go binary out of the specified source files.
|
|
||||||
|
|
||||||
| parameter | type | use | required? |
|
|
||||||
|-----------|-------------------------|------------------------------------------------|-----------|
|
|
||||||
| `name` | `string` | Name of the program (and resulting executable) | yes |
|
|
||||||
| `srcs` | `list<path>` | List of paths to source files | yes |
|
|
||||||
| `deps` | `list<drv>` | List of dependencies (i.e. other Go libraries) | no |
|
|
||||||
| `x_defs` | `attrs<string, string>` | Attribute set of linker vars (i.e. `-X`-flags) | no |
|
|
||||||
|
|
||||||
* `buildGo.package`: Build a Go library out of the specified source files.
|
|
||||||
|
|
||||||
| parameter | type | use | required? |
|
|
||||||
|-----------|--------------|------------------------------------------------|-----------|
|
|
||||||
| `name` | `string` | Name of the library | yes |
|
|
||||||
| `srcs` | `list<path>` | List of paths to source files | yes |
|
|
||||||
| `deps` | `list<drv>` | List of dependencies (i.e. other Go libraries) | no |
|
|
||||||
| `path` | `string` | Go import path for the resulting library | no |
|
|
||||||
|
|
||||||
* `buildGo.external`: Build an externally defined Go library or program.
|
|
||||||
|
|
||||||
This function performs analysis on the supplied source code (which
|
|
||||||
can use the standard Go tooling layout) and creates a tree of all
|
|
||||||
the packages contained within.
|
|
||||||
|
|
||||||
This exists for compatibility with external libraries that were not
|
|
||||||
defined using buildGo.
|
|
||||||
|
|
||||||
| parameter | type | use | required? |
|
|
||||||
|-----------|----------------|-----------------------------------------------|-----------|
|
|
||||||
| `path` | `string` | Go import path for the resulting package | yes |
|
|
||||||
| `src` | `path` | Path to the source **directory** | yes |
|
|
||||||
| `deps` | `list<drv>` | List of dependencies (i.e. other Go packages) | no |
|
|
||||||
|
|
||||||
## Current status
|
|
||||||
|
|
||||||
This project is work-in-progress. Crucially it is lacking the following features:
|
|
||||||
|
|
||||||
* feature flag parity with Bazel's Go rules
|
|
||||||
* documentation building
|
|
||||||
* test execution
|
|
||||||
|
|
||||||
There are still some open questions around how to structure some of those
|
|
||||||
features in Nix.
|
|
||||||
|
|
||||||
[Nix]: https://nixos.org/nix/
|
|
||||||
[Go]: https://golang.org/
|
|
||||||
[Nixery]: https://github.com/google/nixery
|
|
||||||
[Bazel]: https://bazel.build/
|
|
||||||
[like Google]: https://ai.google/research/pubs/pub45424
|
|
||||||
[nix-1p]: https://github.com/tazjin/nix-1p
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
||||||
# Copyright 2019 Google LLC.
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
#
|
|
||||||
# buildGo provides Nix functions to build Go packages in the style of Bazel's
|
|
||||||
# rules_go.
|
|
||||||
|
|
||||||
{ pkgs ? import <nixpkgs> { }
|
|
||||||
, ...
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (builtins)
|
|
||||||
attrNames
|
|
||||||
baseNameOf
|
|
||||||
dirOf
|
|
||||||
elemAt
|
|
||||||
filter
|
|
||||||
listToAttrs
|
|
||||||
map
|
|
||||||
match
|
|
||||||
readDir
|
|
||||||
replaceStrings
|
|
||||||
toString;
|
|
||||||
|
|
||||||
inherit (pkgs) lib runCommand fetchFromGitHub protobuf symlinkJoin go;
|
|
||||||
goStdlib = buildStdlib go;
|
|
||||||
|
|
||||||
# Helpers for low-level Go compiler invocations
|
|
||||||
spaceOut = lib.concatStringsSep " ";
|
|
||||||
|
|
||||||
includeDepSrc = dep: "-I ${dep}";
|
|
||||||
includeSources = deps: spaceOut (map includeDepSrc deps);
|
|
||||||
|
|
||||||
includeDepLib = dep: "-L ${dep}";
|
|
||||||
includeLibs = deps: spaceOut (map includeDepLib deps);
|
|
||||||
|
|
||||||
srcBasename = src: elemAt (match "([a-z0-9]{32}\-)?(.*\.go)" (baseNameOf src)) 1;
|
|
||||||
srcCopy = path: src: "cp ${src} $out/${path}/${srcBasename src}";
|
|
||||||
srcList = path: srcs: lib.concatStringsSep "\n" (map (srcCopy path) srcs);
|
|
||||||
|
|
||||||
allDeps = deps: lib.unique (lib.flatten (deps ++ (map (d: d.goDeps) deps)));
|
|
||||||
|
|
||||||
xFlags = x_defs: spaceOut (map (k: "-X ${k}=${x_defs."${k}"}") (attrNames x_defs));
|
|
||||||
|
|
||||||
# Add an `overrideGo` attribute to a function result that works
|
|
||||||
# similar to `overrideAttrs`, but is used specifically for the
|
|
||||||
# arguments passed to Go builders.
|
|
||||||
makeOverridable = f: orig: (f orig) // {
|
|
||||||
overrideGo = new: makeOverridable f (orig // (new orig));
|
|
||||||
};
|
|
||||||
|
|
||||||
buildStdlib = go: runCommand "go-stdlib-${go.version}"
|
|
||||||
{
|
|
||||||
nativeBuildInputs = [ go ];
|
|
||||||
} ''
|
|
||||||
HOME=$NIX_BUILD_TOP/home
|
|
||||||
mkdir $HOME
|
|
||||||
|
|
||||||
goroot="$(go env GOROOT)"
|
|
||||||
cp -R "$goroot/src" "$goroot/pkg" .
|
|
||||||
|
|
||||||
chmod -R +w .
|
|
||||||
GODEBUG=installgoroot=all GOROOT=$NIX_BUILD_TOP go install -v --trimpath std
|
|
||||||
|
|
||||||
mkdir $out
|
|
||||||
cp -r pkg/*_*/* $out
|
|
||||||
|
|
||||||
find $out -name '*.a' | while read -r ARCHIVE_FULL; do
|
|
||||||
ARCHIVE="''${ARCHIVE_FULL#"$out/"}"
|
|
||||||
PACKAGE="''${ARCHIVE%.a}"
|
|
||||||
echo "packagefile $PACKAGE=$ARCHIVE_FULL"
|
|
||||||
done > $out/importcfg
|
|
||||||
'';
|
|
||||||
|
|
||||||
importcfgCmd = { name, deps, out ? "importcfg" }: ''
|
|
||||||
echo "# nix buildGo ${name}" > "${out}"
|
|
||||||
cat "${goStdlib}/importcfg" >> "${out}"
|
|
||||||
${lib.concatStringsSep "\n" (map (dep: ''
|
|
||||||
find "${dep}" -name '*.a' | while read -r pkgp; do
|
|
||||||
relpath="''${pkgp#"${dep}/"}"
|
|
||||||
pkgname="''${relpath%.a}"
|
|
||||||
echo "packagefile $pkgname=$pkgp"
|
|
||||||
done >> "${out}"
|
|
||||||
'') deps)}
|
|
||||||
'';
|
|
||||||
|
|
||||||
# High-level build functions
|
|
||||||
|
|
||||||
# Build a Go program out of the specified files and dependencies.
|
|
||||||
program = { name, srcs, deps ? [ ], x_defs ? { } }:
|
|
||||||
let uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
|
||||||
in runCommand name { } ''
|
|
||||||
${importcfgCmd { inherit name; deps = uniqueDeps; }}
|
|
||||||
${go}/bin/go tool compile -o ${name}.a -importcfg=importcfg -trimpath=$PWD -trimpath=${go} -p main ${includeSources uniqueDeps} ${spaceOut srcs}
|
|
||||||
mkdir -p $out/bin
|
|
||||||
export GOROOT_FINAL=go
|
|
||||||
${go}/bin/go tool link -o $out/bin/${name} -importcfg=importcfg -buildid nix ${xFlags x_defs} ${includeLibs uniqueDeps} ${name}.a
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Build a Go library assembled out of the specified files.
|
|
||||||
#
|
|
||||||
# This outputs both the sources and compiled binary, as both are
|
|
||||||
# needed when downstream packages depend on it.
|
|
||||||
package = { name, srcs, deps ? [ ], path ? name, sfiles ? [ ] }:
|
|
||||||
let
|
|
||||||
uniqueDeps = allDeps (map (d: d.gopkg) deps);
|
|
||||||
|
|
||||||
# The build steps below need to be executed conditionally for Go
|
|
||||||
# assembly if the analyser detected any *.s files.
|
|
||||||
#
|
|
||||||
# This is required for several popular packages (e.g. x/sys).
|
|
||||||
ifAsm = do: lib.optionalString (sfiles != [ ]) do;
|
|
||||||
asmBuild = ifAsm ''
|
|
||||||
${go}/bin/go tool asm -p ${path} -trimpath $PWD -I $PWD -I ${go}/share/go/pkg/include -D GOOS_linux -D GOARCH_amd64 -gensymabis -o ./symabis ${spaceOut sfiles}
|
|
||||||
${go}/bin/go tool asm -p ${path} -trimpath $PWD -I $PWD -I ${go}/share/go/pkg/include -D GOOS_linux -D GOARCH_amd64 -o ./asm.o ${spaceOut sfiles}
|
|
||||||
'';
|
|
||||||
asmLink = ifAsm "-symabis ./symabis -asmhdr $out/go_asm.h";
|
|
||||||
asmPack = ifAsm ''
|
|
||||||
${go}/bin/go tool pack r $out/${path}.a ./asm.o
|
|
||||||
'';
|
|
||||||
|
|
||||||
gopkg = (runCommand "golib-${name}" { } ''
|
|
||||||
mkdir -p $out/${path}
|
|
||||||
${srcList path (map (s: "${s}") srcs)}
|
|
||||||
${asmBuild}
|
|
||||||
${importcfgCmd { inherit name; deps = uniqueDeps; }}
|
|
||||||
${go}/bin/go tool compile -pack ${asmLink} -o $out/${path}.a -importcfg=importcfg -trimpath=$PWD -trimpath=${go} -p ${path} ${includeSources uniqueDeps} ${spaceOut srcs}
|
|
||||||
${asmPack}
|
|
||||||
'').overrideAttrs (_: {
|
|
||||||
passthru = {
|
|
||||||
inherit gopkg;
|
|
||||||
goDeps = uniqueDeps;
|
|
||||||
goImportPath = path;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
in
|
|
||||||
gopkg;
|
|
||||||
|
|
||||||
# Build a tree of Go libraries out of an external Go source
|
|
||||||
# directory that follows the standard Go layout and was not built
|
|
||||||
# with buildGo.nix.
|
|
||||||
#
|
|
||||||
# The derivation for each actual package will reside in an attribute
|
|
||||||
# named "gopkg", and an attribute named "gobin" for binaries.
|
|
||||||
external = import ./external { inherit pkgs program package; };
|
|
||||||
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# Only the high-level builder functions are exposed, but made
|
|
||||||
# overrideable.
|
|
||||||
program = makeOverridable program;
|
|
||||||
package = makeOverridable package;
|
|
||||||
external = makeOverridable external;
|
|
||||||
|
|
||||||
# re-expose the Go version used
|
|
||||||
inherit go;
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
# Copyright 2019 Google LLC.
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
# This file provides examples for how to use the various builder
|
|
||||||
# functions provided by `buildGo`.
|
|
||||||
#
|
|
||||||
# The features used in the example are not exhaustive, but should give
|
|
||||||
# users a quick introduction to how to use buildGo.
|
|
||||||
|
|
||||||
let
|
|
||||||
buildGo = import ../default.nix { };
|
|
||||||
|
|
||||||
# Example use of buildGo.package, which creates an importable Go
|
|
||||||
# package from the specified source files.
|
|
||||||
examplePackage = buildGo.package {
|
|
||||||
name = "example";
|
|
||||||
srcs = [
|
|
||||||
./lib.go
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Example use of buildGo.program, which builds an executable using
|
|
||||||
# the specified name and dependencies (which in turn must have been
|
|
||||||
# created via buildGo.package etc.)
|
|
||||||
in
|
|
||||||
buildGo.program {
|
|
||||||
name = "example";
|
|
||||||
|
|
||||||
srcs = [
|
|
||||||
./main.go
|
|
||||||
];
|
|
||||||
|
|
||||||
deps = [
|
|
||||||
examplePackage
|
|
||||||
];
|
|
||||||
|
|
||||||
x_defs = {
|
|
||||||
"main.Flag" = "successfully";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
// Copyright 2019 Google LLC.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package example
|
|
||||||
|
|
||||||
// UUID returns a totally random, carefully chosen UUID
|
|
||||||
func UUID() string {
|
|
||||||
return "3640932f-ad40-4bc9-b45d-f504a0f5910a"
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
// Copyright 2019 Google LLC.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
//
|
|
||||||
// Package main provides a tiny example program for the Bazel-style
|
|
||||||
// Nix build system for Go.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"example"
|
|
||||||
"exampleproto"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Flag string = "unsuccessfully"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
thing := exampleproto.Thing{
|
|
||||||
Id: example.UUID(),
|
|
||||||
KindOfThing: "test thing",
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("The thing is a %s with ID %q\n", thing.Id, thing.KindOfThing)
|
|
||||||
fmt.Printf("The flag has been %s set\n", Flag)
|
|
||||||
}
|
|
||||||
112
nix/buildGo/external/default.nix
vendored
112
nix/buildGo/external/default.nix
vendored
|
|
@ -1,112 +0,0 @@
|
||||||
# Copyright 2019 Google LLC.
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
{ pkgs, program, package }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (builtins)
|
|
||||||
elemAt
|
|
||||||
foldl'
|
|
||||||
fromJSON
|
|
||||||
head
|
|
||||||
length
|
|
||||||
listToAttrs
|
|
||||||
readFile
|
|
||||||
replaceStrings
|
|
||||||
tail
|
|
||||||
unsafeDiscardStringContext
|
|
||||||
throw;
|
|
||||||
|
|
||||||
inherit (pkgs) lib runCommand go jq ripgrep;
|
|
||||||
|
|
||||||
pathToName = p: replaceStrings [ "/" ] [ "_" ] (toString p);
|
|
||||||
|
|
||||||
# Collect all non-vendored dependencies from the Go standard library
|
|
||||||
# into a file that can be used to filter them out when processing
|
|
||||||
# dependencies.
|
|
||||||
stdlibPackages = runCommand "stdlib-pkgs.json" { } ''
|
|
||||||
export HOME=$PWD
|
|
||||||
export GOPATH=/dev/null
|
|
||||||
${go}/bin/go list std | \
|
|
||||||
${ripgrep}/bin/rg -v 'vendor' | \
|
|
||||||
${jq}/bin/jq -R '.' | \
|
|
||||||
${jq}/bin/jq -c -s 'map({key: ., value: true}) | from_entries' \
|
|
||||||
> $out
|
|
||||||
'';
|
|
||||||
|
|
||||||
analyser = program {
|
|
||||||
name = "analyser";
|
|
||||||
|
|
||||||
srcs = [
|
|
||||||
./main.go
|
|
||||||
];
|
|
||||||
|
|
||||||
x_defs = {
|
|
||||||
"main.stdlibList" = "${stdlibPackages}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
mkset = path: value:
|
|
||||||
if path == [ ] then { gopkg = value; }
|
|
||||||
else { "${head path}" = mkset (tail path) value; };
|
|
||||||
|
|
||||||
last = l: elemAt l ((length l) - 1);
|
|
||||||
|
|
||||||
toPackage = self: src: path: depMap: entry:
|
|
||||||
let
|
|
||||||
localDeps = map
|
|
||||||
(d: lib.attrByPath (d ++ [ "gopkg" ])
|
|
||||||
(
|
|
||||||
throw "missing local dependency '${lib.concatStringsSep "." d}' in '${path}'"
|
|
||||||
)
|
|
||||||
self)
|
|
||||||
entry.localDeps;
|
|
||||||
|
|
||||||
foreignDeps = map
|
|
||||||
(d: lib.attrByPath [ d.path ]
|
|
||||||
(
|
|
||||||
throw "missing foreign dependency '${d.path}' in '${path}, imported at ${d.position}'"
|
|
||||||
)
|
|
||||||
depMap)
|
|
||||||
entry.foreignDeps;
|
|
||||||
|
|
||||||
args = {
|
|
||||||
srcs = map (f: src + ("/" + f)) entry.files;
|
|
||||||
deps = localDeps ++ foreignDeps;
|
|
||||||
};
|
|
||||||
|
|
||||||
libArgs = args // {
|
|
||||||
name = pathToName entry.name;
|
|
||||||
path = lib.concatStringsSep "/" ([ path ] ++ entry.locator);
|
|
||||||
sfiles = map (f: src + ("/" + f)) entry.sfiles;
|
|
||||||
};
|
|
||||||
|
|
||||||
binArgs = args // {
|
|
||||||
name = (last ((lib.splitString "/" path) ++ entry.locator));
|
|
||||||
};
|
|
||||||
in
|
|
||||||
if entry.isCommand then (program binArgs) else (package libArgs);
|
|
||||||
|
|
||||||
in
|
|
||||||
{ src, path, deps ? [ ] }:
|
|
||||||
let
|
|
||||||
# Build a map of dependencies (from their import paths to their
|
|
||||||
# derivation) so that they can be conditionally imported only in
|
|
||||||
# sub-packages that require them.
|
|
||||||
depMap = listToAttrs (map
|
|
||||||
(d: {
|
|
||||||
name = d.goImportPath;
|
|
||||||
value = d;
|
|
||||||
})
|
|
||||||
(map (d: d.gopkg) deps));
|
|
||||||
|
|
||||||
name = pathToName path;
|
|
||||||
analysisOutput = runCommand "${name}-structure.json" { } ''
|
|
||||||
${analyser}/bin/analyser -path ${path} -source ${src} > $out
|
|
||||||
'';
|
|
||||||
# readFile adds the references of the read in file to the string context for
|
|
||||||
# Nix >= 2.6 which would break the attribute set construction in fromJSON
|
|
||||||
analysis = fromJSON (unsafeDiscardStringContext (readFile analysisOutput));
|
|
||||||
in
|
|
||||||
lib.fix (self: foldl' lib.recursiveUpdate { } (
|
|
||||||
map (entry: mkset entry.locator (toPackage self src path depMap entry)) analysis
|
|
||||||
))
|
|
||||||
200
nix/buildGo/external/main.go
vendored
200
nix/buildGo/external/main.go
vendored
|
|
@ -1,200 +0,0 @@
|
||||||
// Copyright 2019 Google LLC.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// This tool analyses external (i.e. not built with `buildGo.nix`) Go
|
|
||||||
// packages to determine a build plan that Nix can import.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"go/build"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Path to a JSON file describing all standard library import paths.
|
|
||||||
// This file is generated and set here by Nix during the build
|
|
||||||
// process.
|
|
||||||
var stdlibList string
|
|
||||||
|
|
||||||
// pkg describes a single Go package within the specified source
|
|
||||||
// directory.
|
|
||||||
//
|
|
||||||
// Return information includes the local (relative from project root)
|
|
||||||
// and external (none-stdlib) dependencies of this package.
|
|
||||||
type pkg struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Locator []string `json:"locator"`
|
|
||||||
Files []string `json:"files"`
|
|
||||||
SFiles []string `json:"sfiles"`
|
|
||||||
LocalDeps [][]string `json:"localDeps"`
|
|
||||||
ForeignDeps []foreignDep `json:"foreignDeps"`
|
|
||||||
IsCommand bool `json:"isCommand"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type foreignDep struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
// filename, column and line number of the import, if known
|
|
||||||
Position string `json:"position"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// findGoDirs returns a filepath.WalkFunc that identifies all
|
|
||||||
// directories that contain Go source code in a certain tree.
|
|
||||||
func findGoDirs(at string) ([]string, error) {
|
|
||||||
dirSet := make(map[string]bool)
|
|
||||||
|
|
||||||
err := filepath.Walk(at, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
name := info.Name()
|
|
||||||
// Skip folders that are guaranteed to not be relevant
|
|
||||||
if info.IsDir() && (name == "testdata" || name == ".git") {
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the current file is a Go file, then the directory is popped
|
|
||||||
// (i.e. marked as a Go directory).
|
|
||||||
if !info.IsDir() && strings.HasSuffix(name, ".go") && !strings.HasSuffix(name, "_test.go") {
|
|
||||||
dirSet[filepath.Dir(path)] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
goDirs := []string{}
|
|
||||||
for goDir := range dirSet {
|
|
||||||
goDirs = append(goDirs, goDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
return goDirs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// analysePackage loads and analyses the imports of a single Go
|
|
||||||
// package, returning the data that is required by the Nix code to
|
|
||||||
// generate a derivation for this package.
|
|
||||||
func analysePackage(root, source, importpath string, stdlib map[string]bool) (pkg, error) {
|
|
||||||
ctx := build.Default
|
|
||||||
ctx.CgoEnabled = false
|
|
||||||
|
|
||||||
p, err := ctx.ImportDir(source, build.IgnoreVendor)
|
|
||||||
if err != nil {
|
|
||||||
return pkg{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
local := [][]string{}
|
|
||||||
foreign := []foreignDep{}
|
|
||||||
|
|
||||||
for _, i := range p.Imports {
|
|
||||||
if stdlib[i] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if i == importpath {
|
|
||||||
local = append(local, []string{})
|
|
||||||
} else if strings.HasPrefix(i, importpath+"/") {
|
|
||||||
local = append(local, strings.Split(strings.TrimPrefix(i, importpath+"/"), "/"))
|
|
||||||
} else {
|
|
||||||
// The import positions is a map keyed on the import name.
|
|
||||||
// The value is a list, presumably because an import can appear
|
|
||||||
// multiple times in a package. Let’s just take the first one,
|
|
||||||
// should be enough for a good error message.
|
|
||||||
firstPos := p.ImportPos[i][0].String()
|
|
||||||
foreign = append(foreign, foreignDep{Path: i, Position: firstPos})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prefix := strings.TrimPrefix(source, root+"/")
|
|
||||||
|
|
||||||
locator := []string{}
|
|
||||||
if len(prefix) != len(source) {
|
|
||||||
locator = strings.Split(prefix, "/")
|
|
||||||
} else {
|
|
||||||
// Otherwise, the locator is empty since its the root package and
|
|
||||||
// no prefix should be added to files.
|
|
||||||
prefix = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
files := []string{}
|
|
||||||
for _, f := range p.GoFiles {
|
|
||||||
files = append(files, path.Join(prefix, f))
|
|
||||||
}
|
|
||||||
|
|
||||||
sfiles := []string{}
|
|
||||||
for _, f := range p.SFiles {
|
|
||||||
sfiles = append(sfiles, path.Join(prefix, f))
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkg{
|
|
||||||
Name: path.Join(importpath, prefix),
|
|
||||||
Locator: locator,
|
|
||||||
Files: files,
|
|
||||||
SFiles: sfiles,
|
|
||||||
LocalDeps: local,
|
|
||||||
ForeignDeps: foreign,
|
|
||||||
IsCommand: p.IsCommand(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadStdlibPkgs(from string) (pkgs map[string]bool, err error) {
|
|
||||||
f, err := os.ReadFile(from)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(f, &pkgs)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
source := flag.String("source", "", "path to directory with sources to process")
|
|
||||||
path := flag.String("path", "", "import path for the package")
|
|
||||||
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if *source == "" {
|
|
||||||
log.Fatalf("-source flag must be specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
stdlibPkgs, err := loadStdlibPkgs(stdlibList)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to load standard library index from %q: %s\n", stdlibList, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
goDirs, err := findGoDirs(*source)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to walk source directory '%s': %s", *source, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
all := []pkg{}
|
|
||||||
for _, d := range goDirs {
|
|
||||||
analysed, err := analysePackage(*source, d, *path, stdlibPkgs)
|
|
||||||
|
|
||||||
// If the Go source analysis returned "no buildable Go files",
|
|
||||||
// that directory should be skipped.
|
|
||||||
//
|
|
||||||
// This might be due to `+build` flags on the platform and other
|
|
||||||
// reasons (such as test files).
|
|
||||||
if _, ok := err.(*build.NoGoError); ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to analyse package at %q: %s", d, err)
|
|
||||||
}
|
|
||||||
all = append(all, analysed)
|
|
||||||
}
|
|
||||||
|
|
||||||
j, _ := json.Marshal(all)
|
|
||||||
fmt.Println(string(j))
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "cloud.google.com/go";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://code.googlesource.com/gocloud";
|
|
||||||
rev = "4f03f8e4ba168c636e1c218da7ab41a1c8c0d8cf";
|
|
||||||
hash = "sha256:1cgr8f9349r4ymp2k0x49lby47jgi40bblvl1dk6i99ij6faj93d";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/cenkalti/backoff/v4";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "cenkalti";
|
|
||||||
repo = "backoff";
|
|
||||||
rev = "18fe4ce5a8550e0d0919b680ad3c080a5455bddf";
|
|
||||||
sha256 = "083617p066p77ik0js8wwgb5qzabgvl8wqpkjb8s9alpyqsq2mpg";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/charmbracelet/bubbles";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "charmbracelet";
|
|
||||||
repo = "bubbles";
|
|
||||||
# unreleased version required by bubbletea
|
|
||||||
rev = "v0.7.6";
|
|
||||||
sha256 = "1gd4k4f2mj2dnqcbpdrh9plziz0l29ls6mgyy4mfdcdfijfyd30n";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".charmbracelet.bubbletea
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/charmbracelet/bubbletea";
|
|
||||||
src =
|
|
||||||
let
|
|
||||||
gitSrc = pkgs.fetchFromGitHub {
|
|
||||||
owner = "charmbracelet";
|
|
||||||
repo = "bubbletea";
|
|
||||||
rev = "v0.13.1";
|
|
||||||
sha256 = "0yf2fjkvx8ym9n6f3qp2z7sxs0qsfpj148sfvbrp38k67s3h20cs";
|
|
||||||
};
|
|
||||||
# The examples/ directory is fairly extensive,
|
|
||||||
# but it also adds most of the dependencies.
|
|
||||||
in
|
|
||||||
pkgs.runCommand gitSrc.name { } ''
|
|
||||||
mkdir -p $out
|
|
||||||
ln -s "${gitSrc}"/* $out
|
|
||||||
rm -r $out/examples
|
|
||||||
rm -r $out/tutorials
|
|
||||||
'';
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".containerd.console
|
|
||||||
gopkgs."github.com".mattn.go-isatty
|
|
||||||
gopkgs."github.com".muesli.reflow.truncate
|
|
||||||
gopkgs."github.com".muesli.termenv
|
|
||||||
gopkgs."golang.org".x.sys.unix
|
|
||||||
gopkgs."golang.org".x.crypto.ssh.terminal
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/charmbracelet/lipgloss";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "charmbracelet";
|
|
||||||
repo = "lipgloss";
|
|
||||||
# unreleased version required by bubbletea
|
|
||||||
rev = "v0.1.0";
|
|
||||||
sha256 = "1chhs492rsq7i4mr6qpjv3d89rvsd23ri6psnmil3ah6i286vl06";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
# gopkgs."github.com".charmbracelet.bubbletea
|
|
||||||
gopkgs."github.com".lucasb-eyer.go-colorful
|
|
||||||
gopkgs."github.com".muesli.reflow.ansi
|
|
||||||
gopkgs."github.com".muesli.reflow.truncate
|
|
||||||
gopkgs."github.com".muesli.reflow.wordwrap
|
|
||||||
gopkgs."github.com".muesli.termenv
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/containerd/console";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "containerd";
|
|
||||||
repo = "console";
|
|
||||||
rev = "v1.0.1";
|
|
||||||
sha256 = "0s837wj6h80fykk2pdmaji75rw9c3863by0gh0cq51hh0lgyjpvg";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.sys.unix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/davecgh/go-spew";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "davecgh";
|
|
||||||
repo = "go-spew";
|
|
||||||
rev = "8991bc29aa16c548c550c7ff78260e27b9ab7c73";
|
|
||||||
sha256 = "0hka6hmyvp701adzag2g26cxdj47g21x6jz4sc6jjz1mn59d474y";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/emirpasic/gods";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "emirpasic";
|
|
||||||
repo = "gods";
|
|
||||||
rev = "4e23915b9a82f35f320a68a395a7a5045c826932";
|
|
||||||
sha256 = "00f8ch1rccakc62f9nj97hapvnx84z7wbcdmbmz7p802b9mxk5nl";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/golang/glog";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "golang";
|
|
||||||
repo = "glog";
|
|
||||||
rev = "23def4e6c14b4da8ac2ed8007337bc5eb5007998";
|
|
||||||
sha256 = "0jb2834rw5sykfr937fxi8hxi2zy80sj2bdn9b3jb4b26ksqng30";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/golang/groupcache";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://github.com/golang/groupcache";
|
|
||||||
rev = "611e8accdfc92c4187d399e95ce826046d4c8d73";
|
|
||||||
hash = "sha256:0ydaq1xn03h2arfdri0vcv0df19pk8dvq4ly5hm1kv18yjfv1v13";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".golang.protobuf.proto
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/golang/protobuf";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://github.com/golang/protobuf";
|
|
||||||
rev = "ed6926b37a637426117ccab59282c3839528a700";
|
|
||||||
hash = "sha256:0fynqrim022x9xi2bivkw19npbz4316v4yr7mb677s9s36z4dc4h";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/google/uuid";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "google";
|
|
||||||
repo = "uuid";
|
|
||||||
rev = "c2e93f3ae59f2904160ceaab466009f965df46d6";
|
|
||||||
sha256 = "0zw8fvl6jqg0fmv6kmvhss0g4gkrbvgyvl2zgy5wdbdlgp4fja0h";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/googleapis/gax-go";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "googleapis";
|
|
||||||
repo = "gax-go";
|
|
||||||
rev = "b443e5a67ec8eeac76f5f384004931878cab24b3";
|
|
||||||
sha256 = "075s8b76l14c9vlchly38hsf28bnr7vzq9q57g2kg1025h004lzw";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.net.trace.gopkg
|
|
||||||
gopkgs."google.golang.org".grpc.gopkg
|
|
||||||
gopkgs."google.golang.org".grpc.codes.gopkg
|
|
||||||
gopkgs."google.golang.org".grpc.status.gopkg
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/hashicorp/golang-lru";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://github.com/hashicorp/golang-lru";
|
|
||||||
rev = "7f827b33c0f158ec5dfbba01bb0b14a4541fd81d";
|
|
||||||
hash = "sha256:1p2igd58xkm8yaj2c2wxiplkf2hj6kxwrg6ss7mx61s5rd71v5xb";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.net.context.ctxhttp
|
|
||||||
gopkgs."cloud.google.com".go.compute.metadata
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/jbenet/go-context";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "jbenet";
|
|
||||||
repo = "go-context";
|
|
||||||
rev = "d14ea06fba99483203c19d92cfcd13ebe73135f4";
|
|
||||||
sha256 = "0q91f5549n81w3z5927n4a1mdh220bdmgl42zi3h992dcc4ls0sl";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.net.context
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/kevinburke/ssh_config";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "kevinburke";
|
|
||||||
repo = "ssh_config";
|
|
||||||
rev = "01f96b0aa0cdcaa93f9495f89bbc6cb5a992ce6e";
|
|
||||||
sha256 = "1bxfjkjl3ibzdkwyvgdwawmd0skz30ah1ha10rg6fkxvj7lgg4jz";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/lucasb-eyer/go-colorful";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "lucasb-eyer";
|
|
||||||
repo = "go-colorful";
|
|
||||||
# unreleased version required by bubbletea
|
|
||||||
rev = "v1.2.0";
|
|
||||||
sha256 = "08c3fkf27r16izjjd4w94xd1z7w1r4mdalbl53ms2ka2j465s3qs";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/mattn/go-isatty";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "mattn";
|
|
||||||
repo = "go-isatty";
|
|
||||||
rev = "v0.0.12";
|
|
||||||
sha256 = "1dfsh27d52wmz0nmmzm2382pfrs2fcijvh6cgir7jbb4pnigr5w4";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.sys.unix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/mattn/go-runewidth";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "mattn";
|
|
||||||
repo = "go-runewidth";
|
|
||||||
rev = "v0.0.10";
|
|
||||||
sha256 = "0jh9552ppqvkdfni7x623n0x5mbiaqqhjhmr0zkh28x56k4ysii4";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".rivo.uniseg
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/mitchellh/go-homedir";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "mitchellh";
|
|
||||||
repo = "go-homedir";
|
|
||||||
rev = "af06845cf3004701891bf4fdb884bfe4920b3727";
|
|
||||||
sha256 = "0ydzkipf28hwj2bfxqmwlww47khyk6d152xax4bnyh60f4lq3nx1";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/muesli/reflow";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "muesli";
|
|
||||||
repo = "reflow";
|
|
||||||
# unreleased version required by bubbletea
|
|
||||||
rev = "9e1d0d53df68baf262851201166872afafd04e5d";
|
|
||||||
sha256 = "08bmkqdn7sb5laqc1mvgk4xj31f600n1y04s1ifppjvszbcsxhid";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".mattn.go-runewidth
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/muesli/termenv";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "muesli";
|
|
||||||
repo = "termenv";
|
|
||||||
# unreleased version required by bubbletea
|
|
||||||
rev = "v0.8.1";
|
|
||||||
sha256 = "0m24ljq1nq7z933fcvg99fw0fhxj9rb5ll4rlay7z2f2p59mrbdp";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".lucasb-eyer.go-colorful
|
|
||||||
gopkgs."github.com".mattn.go-isatty
|
|
||||||
gopkgs."github.com".mattn.go-runewidth
|
|
||||||
gopkgs."golang.org".x.sys.unix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/pkg/browser";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "pkg";
|
|
||||||
repo = "browser";
|
|
||||||
rev = "0a3d74bf9ce488f035cf5bc36f753a711bc74334";
|
|
||||||
sha256 = "0lv6kwvm31n79mh14a63zslaf4l9bspi2q0i8i9im4njfl42iv1c";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/rivo/uniseg";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "rivo";
|
|
||||||
repo = "uniseg";
|
|
||||||
rev = "v0.1.0";
|
|
||||||
sha256 = "0flpc1px1l6b1lxzhdxi0mvpkkjchppvgxshxxnlmm40s76i9ww5";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/sergi/go-diff";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "sergi";
|
|
||||||
repo = "go-diff";
|
|
||||||
rev = "58c5cb1602ee9676b5d3590d782bedde80706fcc";
|
|
||||||
sha256 = "0ir8ali2vx0j7pipmlfd6k8c973akyy2nmbjrf008fm800zcp7z2";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/src-d/gcfg";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "src-d";
|
|
||||||
repo = "gcfg";
|
|
||||||
rev = "1ac3a1ac202429a54835fe8408a92880156b489d";
|
|
||||||
sha256 = "044j95skmyrwjw5fwjk6ka32rjgsg0ar0mfp9np19sh1acwv4x4r";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."gopkg.in".warnings
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "github.com/xanzy/ssh-agent";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "xanzy";
|
|
||||||
repo = "ssh-agent";
|
|
||||||
rev = "6a3e2ff9e7c564f36873c2e36413f634534f1c44";
|
|
||||||
sha256 = "1chjlnv5d6svpymxgsr62d992m2xi6jb5lybjc5zn1h3hv1m01av";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.crypto.ssh.agent
|
|
||||||
];
|
|
||||||
}
|
|
||||||
17
third_party/gopkgs/go.opencensus.io/default.nix
vendored
17
third_party/gopkgs/go.opencensus.io/default.nix
vendored
|
|
@ -1,17 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "go.opencensus.io";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "census-instrumentation";
|
|
||||||
repo = "opencensus-go";
|
|
||||||
rev = "643eada29081047b355cfaa1ceb9bc307a10423c";
|
|
||||||
sha256 = "1acmv2f5wz06abphk0yvb9igp2j5sn1v21dg1p8n109rwanwd5v4";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".hashicorp.golang-lru.simplelru
|
|
||||||
gopkgs."github.com".golang.groupcache.lru
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "golang.org/x/crypto";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://go.googlesource.com/crypto";
|
|
||||||
rev = "e9b2fee46413994441b28dfca259d911d963dfed";
|
|
||||||
hash = "sha256:18sz5426h320l9gdll9n43lzzxg2dmqv0s5fjy6sbvbkkpjs1m28";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.sys.unix.gopkg
|
|
||||||
];
|
|
||||||
}
|
|
||||||
17
third_party/gopkgs/golang.org/x/net/default.nix
vendored
17
third_party/gopkgs/golang.org/x/net/default.nix
vendored
|
|
@ -1,17 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "golang.org/x/net";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://go.googlesource.com/net";
|
|
||||||
rev = "c0dbc17a35534bf2e581d7a942408dc936316da4";
|
|
||||||
hash = "sha256:1f1xqh2cvr629fkg9n9k347vf6g91jkrsmgmy8hlqdrq163blb54";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.text.secure.bidirule.gopkg
|
|
||||||
gopkgs."golang.org".x.text.unicode.bidi.gopkg
|
|
||||||
gopkgs."golang.org".x.text.unicode.norm.gopkg
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "golang.org/x/oauth2";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://go.googlesource.com/oauth2";
|
|
||||||
rev = "858c2ad4c8b6c5d10852cb89079f6ca1c7309787";
|
|
||||||
hash = "sha256:1dc7n8ddph8w6q0i3cwlgvjwpf2wlkx407va1ydnazasi1j5ixrw";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.net.context.ctxhttp
|
|
||||||
gopkgs."cloud.google.com".go.compute.metadata
|
|
||||||
];
|
|
||||||
}
|
|
||||||
11
third_party/gopkgs/golang.org/x/sys/default.nix
vendored
11
third_party/gopkgs/golang.org/x/sys/default.nix
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "golang.org/x/sys";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://go.googlesource.com/sys";
|
|
||||||
rev = "ac6580df4449443a05718fd7858c1f91ad5f8d20";
|
|
||||||
hash = "sha256:14gvx65w5lddi20s4wypbbvbg9ni3m8777jhp9nqxhixc61k3dyi";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
11
third_party/gopkgs/golang.org/x/text/default.nix
vendored
11
third_party/gopkgs/golang.org/x/text/default.nix
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "golang.org/x/text";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://go.googlesource.com/text";
|
|
||||||
rev = "cbf43d21aaebfdfeb81d91a5f444d13a3046e686";
|
|
||||||
hash = "sha256:1h6z2x4ijzd1126zk3lf8f3bp98j1irs7xg6p8nwpymkqkw5laq8";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
11
third_party/gopkgs/golang.org/x/time/default.nix
vendored
11
third_party/gopkgs/golang.org/x/time/default.nix
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "golang.org/x/time";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://go.googlesource.com/time";
|
|
||||||
rev = "555d28b269f0569763d25dbe1a237ae74c6bcc82";
|
|
||||||
hash = "sha256:1rhl4lyz030kwfsg63yk83yd3ivryv1afmzdz9sxbhcj84ym6h4r";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "google.golang.org/api";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://code.googlesource.com/google-api-go-client";
|
|
||||||
rev = "8b4e46d953bd748a9ff098644a42389b3d8dab41";
|
|
||||||
hash = "sha256:1vffav53qkksrhdqnp8013v90ks6d7jra0vh3sbybg0v0bka7n3p";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".googleapis.gax-go.v2
|
|
||||||
gopkgs."golang.org".x.oauth2.google
|
|
||||||
gopkgs."golang.org".x.oauth2
|
|
||||||
gopkgs."google.golang.org".grpc
|
|
||||||
gopkgs."google.golang.org".grpc.naming
|
|
||||||
gopkgs."go.opencensus.io".plugin.ochttp
|
|
||||||
gopkgs."go.opencensus.io".trace
|
|
||||||
gopkgs."go.opencensus.io".trace.propagation
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "google.golang.org/genproto";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://github.com/google/go-genproto";
|
|
||||||
rev = "0243a4be9c8f1264d238fdc2895620b4d9baf9e1";
|
|
||||||
hash = "sha256:071672lk0pzns98ncbqk6np7l9flwh84hjjibhhm2s1fi941m6q3";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".golang.protobuf.proto.gopkg
|
|
||||||
gopkgs."github.com".golang.protobuf.ptypes.any.gopkg
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "google.golang.org/grpc";
|
|
||||||
|
|
||||||
src = pkgs.fetchgit {
|
|
||||||
url = "https://github.com/grpc/grpc-go";
|
|
||||||
rev = "085c980048876e2735d4aba8f0d5bca4d7acaaa5";
|
|
||||||
hash = "sha256:1vl089pv8qgxkbdg10kyd7203psn35wwjzxxbvi22628faqcpg61";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.net.trace
|
|
||||||
gopkgs."golang.org".x.net.http2
|
|
||||||
gopkgs."golang.org".x.net.http2.hpack
|
|
||||||
gopkgs."golang.org".x.sys.unix
|
|
||||||
gopkgs."github.com".golang.protobuf.proto
|
|
||||||
gopkgs."github.com".golang.protobuf.ptypes
|
|
||||||
gopkgs."github.com".golang.protobuf.ptypes.duration
|
|
||||||
gopkgs."github.com".golang.protobuf.ptypes.timestamp
|
|
||||||
gopkgs."google.golang.org".genproto.googleapis.rpc.status
|
|
||||||
];
|
|
||||||
}
|
|
||||||
17
third_party/gopkgs/googlemaps.github.io/maps.nix
vendored
17
third_party/gopkgs/googlemaps.github.io/maps.nix
vendored
|
|
@ -1,17 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "googlemaps.github.io/maps";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "googlemaps";
|
|
||||||
repo = "google-maps-services-go";
|
|
||||||
rev = "a46d9fca56ac82caa79408b2417ea93a75e3b986";
|
|
||||||
sha256 = "1zpl85yd3m417060isdlhxzakqkf4f59jgpz3kcjp2i0mkrskkjs";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".google.uuid
|
|
||||||
gopkgs."golang.org".x.time.rate
|
|
||||||
];
|
|
||||||
}
|
|
||||||
12
third_party/gopkgs/gopkg.in/irc.v3/default.nix
vendored
12
third_party/gopkgs/gopkg.in/irc.v3/default.nix
vendored
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "gopkg.in/irc.v3";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "go-irc";
|
|
||||||
repo = "irc";
|
|
||||||
rev = "21a5301d6035ea204b2a7bb522a7b4598e5f6b28";
|
|
||||||
sha256 = "1pi5y73pr4prhw5bvmp4babiw02nndizgmpksdgrrg28l9f2wm0n";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "gopkg.in/src-d/go-billy.v4";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "src-d";
|
|
||||||
repo = "go-billy";
|
|
||||||
rev = "fd409ff12f33d0d60af0ce0abeb8d93df360af49";
|
|
||||||
sha256 = "1j0pl6ggzmd2lrqj71vmsnl6cqm43145h7yg6sy3j5n7hhd592qv";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."golang.org".x.sys.unix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
# .v4 is used throughout the codebase and I can't be bothered to do
|
|
||||||
# anything else about it other than using that package path here.
|
|
||||||
path = "gopkg.in/src-d/go-git.v4";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "src-d";
|
|
||||||
repo = "go-git";
|
|
||||||
rev = "1a7db85bca7027d90afdb5ce711622aaac9feaed";
|
|
||||||
sha256 = "08jl4ljrzzil7c3qcl2y1859nhpgw9ixxy1g40ff7kmq989yhs6v";
|
|
||||||
};
|
|
||||||
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".emirpasic.gods.trees.binaryheap
|
|
||||||
gopkgs."github.com".jbenet.go-context.io
|
|
||||||
gopkgs."github.com".kevinburke.ssh_config
|
|
||||||
gopkgs."github.com".mitchellh.go-homedir
|
|
||||||
gopkgs."github.com".sergi.go-diff.diffmatchpatch
|
|
||||||
gopkgs."github.com".src-d.gcfg
|
|
||||||
gopkgs."github.com".xanzy.ssh-agent
|
|
||||||
gopkgs."golang.org".x.crypto.openpgp
|
|
||||||
gopkgs."golang.org".x.crypto.ssh
|
|
||||||
gopkgs."golang.org".x.crypto.ssh.knownhosts
|
|
||||||
gopkgs."golang.org".x.net.proxy
|
|
||||||
gopkgs."gopkg.in".src-d.go-billy
|
|
||||||
gopkgs."gopkg.in".src-d.go-billy.osfs
|
|
||||||
gopkgs."gopkg.in".src-d.go-billy.util
|
|
||||||
];
|
|
||||||
}
|
|
||||||
12
third_party/gopkgs/gopkg.in/warnings/default.nix
vendored
12
third_party/gopkgs/gopkg.in/warnings/default.nix
vendored
|
|
@ -1,12 +0,0 @@
|
||||||
{ depot, pkgs, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.external {
|
|
||||||
path = "gopkg.in/warnings.v0";
|
|
||||||
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "go-warnings";
|
|
||||||
repo = "warnings";
|
|
||||||
rev = "27b9fabbdaf131d2169ec3ff7db8ffc4d839635e";
|
|
||||||
sha256 = "1y276jd9gwvjriz8yd98k3srgbnmbja8f7f7m6lvr0h5sbq3g3w9";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
{ depot, ... }:
|
|
||||||
|
|
||||||
depot.nix.buildGo.program {
|
|
||||||
name = "when";
|
|
||||||
srcs = [ ./when.go ];
|
|
||||||
}
|
|
||||||
|
|
@ -1,206 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const usage = `usage: when <time>
|
|
||||||
|
|
||||||
This program converts the given time into various formats (currently a local
|
|
||||||
timestamp, UTC timestamp, and UNIX epoch). It tries to guess what the input is.
|
|
||||||
|
|
||||||
Some valid queries:
|
|
||||||
|
|
||||||
2024-01-05
|
|
||||||
1715079241
|
|
||||||
tomorrow 5PM
|
|
||||||
-22h
|
|
||||||
-7h10m
|
|
||||||
Mar 15
|
|
||||||
Sep 3 18:00
|
|
||||||
|
|
||||||
For now a single timestamp and a single duration (which is added either to the
|
|
||||||
current time, or the given time) is supported.`
|
|
||||||
|
|
||||||
func printTime(t time.Time) {
|
|
||||||
fmt.Println("Local:", t.Format("Mon 02 January 2006 at 15:04:05 MST"))
|
|
||||||
fmt.Println("UTC: ", t.UTC().Format(time.RFC3339))
|
|
||||||
fmt.Println("UNIX: ", t.Unix())
|
|
||||||
}
|
|
||||||
|
|
||||||
type FieldSet uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
SetYear FieldSet = 1 << iota
|
|
||||||
SetDay
|
|
||||||
SetMonth
|
|
||||||
SetHour
|
|
||||||
SetMinute
|
|
||||||
SetSecond
|
|
||||||
SetLocation
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
SetDate = SetYear | SetDay | SetMonth
|
|
||||||
SetClock = SetHour | SetMinute | SetSecond
|
|
||||||
)
|
|
||||||
|
|
||||||
// mergeTimes returns a new time.Time with all fields in this overridden with the
|
|
||||||
// specified fields from that.
|
|
||||||
func mergeTimes(this time.Time, that time.Time, set FieldSet) time.Time {
|
|
||||||
year, month, day := this.Date()
|
|
||||||
hour, min, sec := this.Clock()
|
|
||||||
loc := this.Location()
|
|
||||||
|
|
||||||
if set&SetYear == SetYear {
|
|
||||||
year = that.Year()
|
|
||||||
}
|
|
||||||
if set&SetMonth == SetMonth {
|
|
||||||
month = that.Month()
|
|
||||||
}
|
|
||||||
if set&SetDay == SetDay {
|
|
||||||
day = that.Day()
|
|
||||||
}
|
|
||||||
if set&SetHour == SetHour {
|
|
||||||
hour = that.Hour()
|
|
||||||
}
|
|
||||||
if set&SetMinute == SetMinute {
|
|
||||||
min = that.Minute()
|
|
||||||
}
|
|
||||||
if set&SetSecond == SetSecond {
|
|
||||||
sec = that.Second()
|
|
||||||
}
|
|
||||||
if set&SetLocation == SetLocation {
|
|
||||||
loc = that.Location()
|
|
||||||
}
|
|
||||||
|
|
||||||
return time.Date(year, month, day, hour, min, sec, 0, loc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseTime(input string) (time.Time, error) {
|
|
||||||
// try unix times
|
|
||||||
if i, err := strconv.ParseInt(input, 10, 64); err == nil {
|
|
||||||
if i < 9999999999 {
|
|
||||||
return time.Unix(i, 0), nil
|
|
||||||
}
|
|
||||||
if i < 9999999999999 {
|
|
||||||
return time.UnixMilli(i), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// try simple date/time formats
|
|
||||||
if t, err := time.Parse(time.DateOnly, input); err == nil {
|
|
||||||
return t, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := time.Parse(time.Kitchen, input); err == nil {
|
|
||||||
now := time.Now()
|
|
||||||
return mergeTimes(now, t, SetClock), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := time.Parse(time.TimeOnly, input); err == nil {
|
|
||||||
now := time.Now()
|
|
||||||
return mergeTimes(now, t, SetClock), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := time.Parse("15:04", input); err == nil {
|
|
||||||
now := time.Now()
|
|
||||||
return mergeTimes(now, t, SetClock), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := time.Parse("3PM", input); err == nil {
|
|
||||||
now := time.Now()
|
|
||||||
return mergeTimes(now, t, SetClock), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := time.Parse(time.DateTime, input); err == nil {
|
|
||||||
return t, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := time.Parse(time.Stamp, input); err == nil {
|
|
||||||
now := time.Now()
|
|
||||||
return mergeTimes(t, now, SetYear|SetLocation), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := time.Parse("Jan _2 15:04", input); err == nil {
|
|
||||||
now := time.Now()
|
|
||||||
return mergeTimes(t, now, SetYear|SetLocation), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := time.Parse("Jan _2", input); err == nil {
|
|
||||||
now := time.Now()
|
|
||||||
return mergeTimes(t, now, SetYear|SetLocation), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return time.Time{}, fmt.Errorf("could not parse time: %q", input)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseDuration(input string) (time.Duration, error) {
|
|
||||||
// some simple rewriting
|
|
||||||
switch input {
|
|
||||||
case "yesterday":
|
|
||||||
input = "-24h"
|
|
||||||
case "tomorrow":
|
|
||||||
input = "24h"
|
|
||||||
case "today", "now":
|
|
||||||
return time.Duration(0), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: days, months, weeks, ...
|
|
||||||
return time.ParseDuration(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) < 2 {
|
|
||||||
fmt.Fprintln(os.Stderr, usage)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var d time.Duration
|
|
||||||
var t time.Time
|
|
||||||
var err error
|
|
||||||
var haveTime, haveDuration bool
|
|
||||||
|
|
||||||
// Try to parse entire input as one full thing, before getting more
|
|
||||||
// clever.
|
|
||||||
if t, err = parseTime(strings.Join(os.Args[1:], " ")); err == nil {
|
|
||||||
printTime(t)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, arg := range os.Args[1:] {
|
|
||||||
if !haveTime {
|
|
||||||
if t, err = parseTime(arg); err == nil {
|
|
||||||
haveTime = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !haveDuration {
|
|
||||||
if d, err = parseDuration(arg); err == nil {
|
|
||||||
haveDuration = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, "Not sure what you want, try another time.")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if haveTime && haveDuration {
|
|
||||||
printTime(t.Add(d))
|
|
||||||
} else if haveTime {
|
|
||||||
printTime(t)
|
|
||||||
} else if haveDuration {
|
|
||||||
printTime(time.Now().Add(d))
|
|
||||||
} else {
|
|
||||||
fmt.Fprintln(os.Stderr, "Not sure what you want, try another time.")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue