Nigel Tao | a540fbc | 2020-02-25 15:54:53 +1100 | [diff] [blame] | 1 | // Copyright 2020 The Wuffs Authors. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
Nigel Tao | 788479d | 2021-08-22 10:52:51 +1000 | [diff] [blame] | 15 | //go:build ignore |
Nigel Tao | a540fbc | 2020-02-25 15:54:53 +1100 | [diff] [blame] | 16 | // +build ignore |
| 17 | |
| 18 | package main |
| 19 | |
| 20 | // print-file-sizes-json.go prints a JSON object containing the names and sizes |
| 21 | // of the files and directories under the current working directory, |
| 22 | // recursively. |
| 23 | // |
| 24 | // A directory is printed as a JSON object whose keys are its children's names. |
| 25 | // Child directories' values are also JSON objects. Child files' values are the |
| 26 | // file size as a JSON number. |
| 27 | // |
| 28 | // A directory's JSON object also contains a key-value pair for the empty |
| 29 | // string key. Its value is the sum of all children and descendent file sizes. |
| 30 | // Note that this is just the total raw file size, and does not account for any |
| 31 | // file system overhead for directories or for rounding up a file sizes to a |
| 32 | // multiple of a disk block size. |
| 33 | |
| 34 | import ( |
| 35 | "encoding/json" |
| 36 | "os" |
| 37 | "path/filepath" |
| 38 | "strings" |
| 39 | ) |
| 40 | |
| 41 | func main() { |
| 42 | if err := main1(); err != nil { |
| 43 | os.Stderr.WriteString(err.Error() + "\n") |
| 44 | os.Exit(1) |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | func main1() error { |
| 49 | root := dir{"": int64(0)} |
| 50 | |
| 51 | if err := filepath.Walk(".", func(path string, info os.FileInfo, walkErr error) error { |
| 52 | if walkErr != nil { |
| 53 | return walkErr |
| 54 | } |
| 55 | if (path != "") && (path[0] == '.') { |
| 56 | if info.IsDir() && (path != ".") { |
| 57 | return filepath.SkipDir |
| 58 | } |
| 59 | return nil |
| 60 | } |
| 61 | path = filepath.ToSlash(path) |
| 62 | |
| 63 | ancestors := []dir{} |
| 64 | d := root |
| 65 | for remaining := ""; len(path) > 0; path = remaining { |
| 66 | ancestors = append(ancestors, d) |
| 67 | if i := strings.IndexByte(path, '/'); i >= 0 { |
| 68 | path, remaining = path[:i], path[i+1:] |
| 69 | } else { |
| 70 | remaining = "" |
| 71 | } |
| 72 | if (remaining == "") && !info.IsDir() { |
| 73 | n := info.Size() |
| 74 | d[path] = n |
| 75 | for _, a := range ancestors { |
| 76 | a[""] = a[""].(int64) + n |
| 77 | } |
| 78 | } else if next, ok := d[path]; ok { |
| 79 | d = next.(dir) |
| 80 | } else { |
| 81 | next := dir{"": int64(0)} |
| 82 | d[path] = next |
| 83 | d = next |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | return nil |
| 88 | }); err != nil { |
| 89 | return err |
| 90 | } |
| 91 | |
| 92 | if enc, err := json.Marshal(root); err != nil { |
| 93 | return err |
| 94 | } else { |
| 95 | os.Stdout.Write(enc) |
| 96 | } |
| 97 | return nil |
| 98 | } |
| 99 | |
| 100 | type dir map[string]interface{} |