MCPcopy Index your code
hub / github.com/ejholmes/walk

github.com/ejholmes/walk @v0.3.3

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.3.3 ↗ · + Follow
191 symbols 654 edges 29 files 90 documented · 47%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Walk

Build Status Go Report Card Latest Version

walk is a fast, general purpose, graph based build and task execution utility.

Heavily inspired by make and redo.

Features

  • Fast parallel execution.
  • Graph based dependency management.
  • Maximum composability with existing UNIX tooling.
  • Describe targets and their dependencies as simple executables.
  • Universal execution; execute walk from any directory.

Installation

Using Go 1.7+:

$ go get -u github.com/ejholmes/walk

Or grab the latest release from https://github.com/ejholmes/walk/releases.

Usage

walk is built on top of a very simple concept; when you want to build a target, walk executes a file called Walkfile to determine:

  1. What other targets the given target depends on.
  2. How to build the target.

For example, if you wanted to build a program called prog from main.c and parse.c, you might write a Walkfile like this:

#!/bin/bash

# The first argument is the "phase", which will either be `deps` or `exec`. In
# the `deps` phase, the Walkfile should print the name of the targets that this
# target depends on.
phase=$1

# The second argument is the name of the target, like `prog`, `parse.o`, etc.
target=$2

case $target in
  prog)
    case $phase in
      # Prog depends on the object files we'll build from source. We simply
      # print each dependency on a single line.
      deps)
        echo main.o
        echo parse.o
        ;;
      exec) exec gcc -Wall -o $target $($0 deps $target) ;;
    esac ;;

  # A generic recipe for building a .o file from a corresponding .c file.
  *.o)
    case $phase in
      deps) echo ${target//.o/.c} ;;
      exec) exec gcc -Wall -o $target -c $($0 deps $target) ;;
    esac ;;

  # When invoking walk(1) without any arguments, it defaults to a target called
  # `all`.
  all)
    case $phase in
      deps) echo prog ;;
    esac ;;

  # In general, it's good practice to include a fallback rule like this, in
  # case someone tries to build a target that we don't know how to build (or
  # someone makes a typo).
  *.c|*.h) ;; # static files
  *) >&2 echo "No rule for target \"$target\"" && exit 1 ;;
esac

When you execute walk all, the following happens internally:

  1. walk resolves all of the dependencies, and builds a graph:

    console $ Walkfile deps all prog $ Walkfile deps prog parse.o main.o $ Walkfile deps parse.o parse.c $ Walkfile deps main.o main.c $ Walkfile deps parse.c $ Walkfile deps main.c

  2. walk executes all of the targets, starting with dependencies:

    console $ Walkfile exec parse.c $ Walkfile exec main.c $ Walkfile exec main.o $ Walkfile exec parse.o $ Walkfile exec prog $ Walkfile exec all

Ultimately, all of our targets end up getting invoked, and prog is built:

$ walk
ok  main.c
ok  parse.c
ok  parse.o
ok  main.o
ok  prog
ok  all

We can print the dependency graph to verify that our dependency chain is what we expect:

$ walk -p dot
digraph {
  "(root)" -> "all"
  "all" -> "prog"
  "prog" -> "main.o"
  "prog" -> "parse.o"
  "parse.o" -> "parse.c"
  "main.o" -> "main.c"
}

And that's it. Wait, that's it? That's it. walk is quite simply, just syntactic sugar over executing a binary as a graph.

See also man walk.

Extension points exported contracts — how you extend this code

Target (Interface)
Target represents a target, which is usually built by a Rule. In general, targets are represented as paths to files on d [4 …
plan.go
NamedVertex (Interface)
NamedVertex is an optional interface that can be implemented by Vertex to give it a human-friendly name that is used for [4 …
internal/dag/graph.go
Semaphore (Interface)
Semaphore is an interface to represent a Semaphore. This is used when executing a graph to control the number of concurr [1 …
semaphore.go
Rule (Interface)
Rule defines what a target depends on, and how to execute it. [3 implementers]
plan.go
Hashable (Interface)
Hashable is the interface used by set to get the hash code of a value. If this isn't given, then the value of the item b [2 …
internal/dag/set.go
Edge (Interface)
Edge represents an edge in the graph, with a source and target vertex. [1 implementers]
internal/dag/edge.go
WalkFunc (FuncType)
WalkFunc is the callback used for walking the graph.
internal/dag/dag.go
DepthWalkFunc (FuncType)
DepthWalkFunc is a walk function that also receives the current depth of the walk as an argument
internal/dag/dag.go

Core symbols most depended-on inside this repo

BasicEdge
called by 65
internal/dag/edge.go
Connect
called by 56
internal/dag/graph.go
Add
called by 45
internal/dag/set.go
Add
called by 36
internal/dag/graph.go
Name
called by 12
plan.go
hashcode
called by 10
internal/dag/set.go
DownEdges
called by 10
internal/dag/graph.go
List
called by 9
internal/dag/set.go

Shape

Method 84
Function 75
Struct 21
Interface 7
FuncType 2
TypeAlias 2

Languages

Go98%
C2%

Modules by API surface

plan.go29 symbols
graph.go20 symbols
internal/dag/graph.go18 symbols
internal/dag/dag.go18 symbols
internal/dag/dag_test.go12 symbols
internal/dag/set.go11 symbols
internal/dag/graph_test.go11 symbols
semaphore.go10 symbols
plan_test.go10 symbols
internal/dag/tarjan.go8 symbols
internal/dag/edge.go8 symbols
graph_test.go6 symbols

For agents

$ claude mcp add walk \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact