diff -Nru pk4-4/cmd/pk4-edith/edith.css pk4-5/cmd/pk4-edith/edith.css --- pk4-4/cmd/pk4-edith/edith.css 1970-01-01 00:00:00.000000000 +0000 +++ pk4-5/cmd/pk4-edith/edith.css 2017-10-22 07:07:57.000000000 +0000 @@ -0,0 +1,43 @@ +html, body { + width: 100vw; + min-height: 100vh; + margin: 0; + padding: 0; +} + +body { + display: grid; + grid-template-rows: 2em 80vh auto; + /* nav:editor ratio is 3:9 */ + grid-template-columns: minmax(200px, 3fr) 9fr; + grid-template-areas: "nav toolbar" + "nav editor" + "nav pending"; +} + +#navigation { + grid-area: nav; + max-height: 100vh; + background-color: #c0c0c0; + overflow: scroll; +} + +#editor { + grid-area: editor; + max-height: 100%; + overflow: hidden; + background-color: #c0c0ff; +} + +#editor .CodeMirror { + height: 100%; +} + +#toolbar { + grid-area: toolbar; +} + +#pending { + grid-area: pending; + background-color: #c0c000; +} diff -Nru pk4-4/cmd/pk4-edith/edith.go pk4-5/cmd/pk4-edith/edith.go --- pk4-4/cmd/pk4-edith/edith.go 1970-01-01 00:00:00.000000000 +0000 +++ pk4-5/cmd/pk4-edith/edith.go 2017-10-22 07:27:10.000000000 +0000 @@ -0,0 +1,115 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "os" + "path" + "path/filepath" + "sort" + "strings" +) + +type handlerFunc func(w http.ResponseWriter, r *http.Request) error + +func errorTo502(f handlerFunc) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if err := f(w, r); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + }) +} + +// shiftPath splits off the first component of p, which will be cleaned of +// relative components before processing. head will never contain a slash and +// tail will always be a rooted path without trailing slash. +func shiftPath(p string) (head, tail string) { + p = path.Clean("/" + p) + i := strings.Index(p[1:], "/") + 1 + if i <= 0 { + return p[1:], "/" + } + return p[1:i], p[i:] +} + +func listHandler(w http.ResponseWriter, r *http.Request) error { + // TODO: list all packages from /var/cache/pk4/completions.src.txt + fmt.Fprintf(w, "ohai!") + return nil +} + +// lsrHandler returns a recursive listing of filenames of the specified source +// package in the specified version. +// +// It is typically called by the JavaScript editor when opening a source +// package. +func lsrHandler(w http.ResponseWriter, r *http.Request) error { + srcpackage, tail := shiftPath(r.URL.Path) + srcversion, _ := shiftPath(tail) + if srcpackage == "" || srcversion == "" { + return fmt.Errorf("syntax: /ls-R//") + } + // TODO: ensure the package is in the cache beforehand + var paths []string + dir := filepath.Join("/home/michael/.cache/pk4/", srcpackage+"-"+srcversion) + "/" + if err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info != nil && info.IsDir() && + (filepath.Base(path) == ".git" || + filepath.Base(path) == ".pc") { + return filepath.SkipDir + } + if rel := strings.TrimPrefix(path, dir); rel != "" { + paths = append(paths, rel) + } + return nil + }); err != nil { + return err + } + sort.Strings(paths) + if err := json.NewEncoder(w).Encode(paths); err != nil { + return err + } + log.Printf("pkg %q, version %q", srcpackage, srcversion) + return nil +} + +// origHandler serves original, unmodified source package files from the pk4 +// cache. +// +// TODO: use snapshot.d.n instead? +func origHandler(w http.ResponseWriter, r *http.Request) error { + srcpackage, tail1 := shiftPath(r.URL.Path) + srcversion, tail := shiftPath(tail1) + if srcpackage == "" || srcversion == "" { + return fmt.Errorf("syntax: /orig///") + } + log.Printf("pkg %q, version %q, path %q", srcpackage, srcversion, tail) + dir := filepath.Join("/home/michael/.cache/pk4/", srcpackage+"-"+srcversion) + "/" + http.ServeFile(w, r, filepath.Join(dir, tail)) + return nil +} + +func main() { + http.Handle("/", http.FileServer(http.Dir("."))) + http.HandleFunc("/edit/", func(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, "edith.html") + }) + http.Handle("/list", errorTo502(listHandler)) + // TODO: middleware to set cache header to \infty + http.Handle("/ls-R/", http.StripPrefix("/ls-R/", errorTo502(lsrHandler))) + http.Handle("/orig/", http.StripPrefix("/orig/", errorTo502(origHandler))) + log.Fatal(http.ListenAndServe(":3391", nil)) +} + +/* TODO: +envisioned contributor workflow: +1. future contributor creates a guest account (pending state) +2. current DD vouches for that guest account +3. guest account can now be used for authN via sso.d.o +4. authZ is service-specific. e.g., user can create new gitlab repos under their guest-acc space, but not write to any debian ones (yet) +*/ diff -Nru pk4-4/cmd/pk4-edith/edith.html pk4-5/cmd/pk4-edith/edith.html --- pk4-4/cmd/pk4-edith/edith.html 1970-01-01 00:00:00.000000000 +0000 +++ pk4-5/cmd/pk4-edith/edith.html 2017-10-22 07:09:58.000000000 +0000 @@ -0,0 +1,27 @@ + + + + Edith + + + + + + +
+ Save + Diff +
+
+ +
+
+ pending changes pane +
+ + + diff -Nru pk4-4/cmd/pk4-edith/edith.js pk4-5/cmd/pk4-edith/edith.js --- pk4-4/cmd/pk4-edith/edith.js 1970-01-01 00:00:00.000000000 +0000 +++ pk4-5/cmd/pk4-edith/edith.js 2017-10-22 07:09:40.000000000 +0000 @@ -0,0 +1,119 @@ +// TODO: consider using typescript? +console.log('ohai!'); + +// TODO: load list for all packages + +var parts = document.location.pathname.split(/\//); +// TODO: error checking +var srcpackage = parts[2]; +var srcversion = parts[3]; +var path = parts.slice(4).join("/"); + +// TODO: error handling +fetch('/ls-R/' + srcpackage + '/' + srcversion).then(function(response) { + return response.json(); +}).then(function(list) { + // TODO: expandable file tree browser widget. does codemirror have/recommend sth? + var navigationList = document.createElement('ul'); + for (let fn of list) { + var li = document.createElement('li'); + // TODO: click handler to load file in place without triggering a whole app reload + var a = document.createElement('a'); + a.setAttribute('href', '/edit/' + srcpackage + '/' + srcversion + '/' + fn); + a.appendChild(document.createTextNode(fn)); + li.appendChild(a); + navigationList.appendChild(li); + } + document.getElementById('navigation').appendChild(navigationList); +}); + +var ta = document.getElementById('editor-ta'); + +function loadPending(srcpackage, srcversion) { + var pendingKey = JSON.stringify({ + type: 'pending', + srcpackage: srcpackage, + srcversion: srcversion, + }); + var pending = window.localStorage.getItem(pendingKey); + if (pending === null) { + return {}; + } + return JSON.parse(pending); +} + +var pending = loadPending(srcpackage, srcversion); + +var pendingList = document.createElement('ul'); +for (fn in pending) { + var li = document.createElement('li'); + var a = document.createElement('a'); + a.setAttribute('href', '/edit/' + srcpackage + '/' + srcversion + '/' + fn); + a.appendChild(document.createTextNode(fn)); + li.appendChild(a); + pendingList.appendChild(li); +} +document.getElementById('pending').appendChild(pendingList); + +var myCodeMirror; +function load(srcpackage, srcversion, path, pending) { + if (pending[path] === undefined) { + // TODO: error handling + fetch('/orig/' + srcpackage + '/' + srcversion + '/' + path).then(function(response) { + return response.text(); + }).then(function(text) { + ta.value = text; + myCodeMirror = CodeMirror.fromTextArea( + ta, + { + lineNumbers: true, + }); + }); + return; + } + var valueKey = JSON.stringify({ + type: 'file', + srcpackage: srcpackage, + srcversion: srcversion, + path: path, + }); + var value = window.localStorage.getItem(valueKey); + if (!value) { + // TODO: error message: corrupt localStorage + return "corrupt localStorage"; + } + ta.value = value; + myCodeMirror = CodeMirror.fromTextArea( + ta, + { + lineNumbers: true, + }); +} + +load(srcpackage, srcversion, path, pending); + +var saveBtn = document.getElementById('savebtn'); +saveBtn.addEventListener('click', function(ev) { + console.log('save!'); + // TODO: is JSON.stringify guaranteed to be deterministic, or should we use a different key format? + var valueKey = JSON.stringify({ + type: 'file', + srcpackage: srcpackage, + srcversion: srcversion, + path: path, + }); + window.localStorage.setItem(valueKey, myCodeMirror.getValue()); + var pendingKey = JSON.stringify({ + type: 'pending', + srcpackage: srcpackage, + srcversion: srcversion, + }); + var pending = window.localStorage.getItem(pendingKey); + if (pending !== null) { + pending[path] = true + } else { + pending = {path: true}; + } + window.localStorage.setItem(pendingKey, JSON.stringify(pending)); + ev.preventDefault(); +}); diff -Nru pk4-4/debian/changelog pk4-5/debian/changelog --- pk4-4/debian/changelog 2018-01-05 08:35:29.000000000 +0000 +++ pk4-5/debian/changelog 2018-01-14 19:36:08.000000000 +0000 @@ -1,3 +1,9 @@ +pk4 (5) unstable; urgency=medium + + * “avail” → “make available” (closes: #881343) + + -- Michael Stapelberg Sun, 14 Jan 2018 20:36:08 +0100 + pk4 (4) unstable; urgency=medium * pk4-replace.1: add another example to illustrate how options are passed diff -Nru pk4-4/debian/control pk4-5/debian/control --- pk4-4/debian/control 2018-01-05 08:35:29.000000000 +0000 +++ pk4-5/debian/control 2018-01-14 19:34:40.000000000 +0000 @@ -21,7 +21,7 @@ systemd-sysv Recommends: sbuild Built-Using: ${misc:Built-Using} -Description: avail the Debian source package producing the specified package +Description: make available the Debian source package producing the specified package pk4 resolves the specified argument(s) as either: . 1. the name of a Debian binary package, and selects its Debian source package. diff -Nru pk4-4/pk4.1 pk4-5/pk4.1 --- pk4-4/pk4.1 2018-01-05 08:35:29.000000000 +0000 +++ pk4-5/pk4.1 2018-01-14 19:34:30.000000000 +0000 @@ -11,7 +11,7 @@ .TH pk4 1 "OCTOBER 2017" Linux "User Manuals" .SH NAME -pk4 \- avail the Debian source package producing the specified package +pk4 \- make available the Debian source package producing the specified package .SH SYNOPSIS .B pk4 diff -Nru pk4-4/pk4-generate-index.1 pk4-5/pk4-generate-index.1 --- pk4-4/pk4-generate-index.1 2018-01-05 08:35:29.000000000 +0000 +++ pk4-5/pk4-generate-index.1 2018-01-14 19:34:36.000000000 +0000 @@ -32,6 +32,6 @@ .SH SEE ALSO .TP .IR pk4(1) -avail the Debian source package producing the specified package +make available the Debian source package producing the specified package .SH AUTHOR Michael Stapelberg diff -Nru pk4-4/pk4-replace.1 pk4-5/pk4-replace.1 --- pk4-4/pk4-replace.1 2018-01-05 08:35:29.000000000 +0000 +++ pk4-5/pk4-replace.1 2018-01-14 19:34:06.000000000 +0000 @@ -73,7 +73,7 @@ .SH SEE ALSO .TP .IR pk4(1) -avail the Debian source package producing the specified package +make available the Debian source package producing the specified package .TP .IR sbuild(1) build debian packages from source diff -Nru pk4-4/README.md pk4-5/README.md --- pk4-4/README.md 2018-01-05 08:35:29.000000000 +0000 +++ pk4-5/README.md 2018-01-14 19:34:18.000000000 +0000 @@ -1,4 +1,4 @@ -# pk4 — avail the Debian source package producing the specified package +# pk4 — make available the Debian source package producing the specified package Please see [the pk4(1) manpage](https://manpages.debian.org/unstable/pk4/pk4.1.en.html) for @@ -6,8 +6,8 @@ ## Terminal screencast -Here is a terminal screencast of the tool in action, availing the sources of i3, -applying a patch, rebuilding the package and replacing the installed binary -packages: +Here is a terminal screencast of the tool in action, making available the +sources of i3, applying a patch, rebuilding the package and replacing the +installed binary packages: [![asciicast](https://asciinema.org/a/TgYn2wkABiob14WKb2UefNl9f.png)](https://asciinema.org/a/TgYn2wkABiob14WKb2UefNl9f)