github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/hack/prune-libraries.sh (about)

     1  #!/bin/bash
     2  # Copyright 2018 The Kubernetes Authors.
     3  #
     4  # Licensed under the Apache License, Version 2.0 (the "License");
     5  # you may not use this file except in compliance with the License.
     6  # You may obtain a copy of the License at
     7  #
     8  #     http://www.apache.org/licenses/LICENSE-2.0
     9  #
    10  # Unless required by applicable law or agreed to in writing, software
    11  # distributed under the License is distributed on an "AS IS" BASIS,
    12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  # See the License for the specific language governing permissions and
    14  # limitations under the License.
    15  
    16  
    17  # Identifies go_library() bazel targets in the workspace with no dependencies.
    18  # Deletes the target and its files. Cleans up any :all-srcs references
    19  
    20  # By default just checks for extra libraries, run with --fix to make changes.
    21  
    22  
    23  set -o nounset
    24  set -o errexit
    25  set -o pipefail
    26  
    27  # This list is used for rules in vendor/ which may not have any explicit
    28  # dependencies outside of vendor, e.g. helper commands we have vendored.
    29  # It should probably match the list in Gopkg.toml.
    30  REQUIRED=(
    31    //vendor/github.com/bazelbuild/bazel-gazelle/cmd/gazelle:gazelle
    32    //vendor/github.com/golang/dep/cmd/dep:dep
    33    //vendor/github.com/client9/misspell/cmd/misspell:misspell
    34    //vendor/github.com/kubernetes/repo-infra/kazel:kazel
    35  )
    36  
    37  # darwin is great
    38  SED=sed
    39  if which gsed &>/dev/null; then
    40    SED=gsed
    41  fi
    42  if ! ($SED --version 2>&1 | grep -q GNU); then
    43    echo "!!! GNU sed is required.  If on OS X, use 'brew install gnu-sed'." >&2
    44    exit 1
    45  fi
    46  
    47  unused-go-libraries() {
    48    # Find all the go_library rules in vendor except those that something outside
    49    # of vendor eventually depends on.
    50    required_items=( "${REQUIRED[@]/#/+ }" )
    51    echo "Looking for //vendor targets that no one outside of //vendor depends on..." >&2
    52    bazel query "kind('go_library rule', //vendor/... -deps(//... -//vendor/... ${required_items[@]}))"
    53  }
    54  
    55  # Output this:source.go that:file.txt sources of //this //that targets
    56  target-sources() {
    57    (for i in "$@"; do
    58      bazel query "kind(\"source file\", deps(\"$(package-name "$i"):package-srcs\", 1))"
    59    done) | sort -u
    60  }
    61  
    62  sources() {
    63    local t
    64    for j in $(target-sources "${@}"); do
    65      case "$(target-name "$j")" in
    66        LICENSE*|PATENTS*|*.md)  # Keep these files
    67          continue
    68          ;;
    69      esac
    70      echo $(package-name "${j:2}")/$(target-name $j)
    71    done
    72  }
    73  
    74  # Convert //foo:and/bar:stuff to //foo:and/bar
    75  package-name() {
    76    echo ${1%:*}
    77  }
    78  
    79  # Convert //foo:and/bar:stuff to stuff
    80  target-name() {
    81    echo ${1##*:}
    82  }
    83  
    84  # Find every package that directly depends on //foo:all-srcs
    85  all-srcs-refs() {
    86    packages $(for i in "$@"; do
    87      bazel query "rdeps(//..., \"${i}:all-srcs\", 1)"
    88    done)
    89  }
    90  
    91  # Convert //foo/bar:stuff //this //foo/bar:stuff to //foo/bar //this
    92  packages() {
    93    (for i in "$@"; do
    94      echo $(package-name "${i}")
    95    done) | sort -u
    96  }
    97  
    98  # Convert //foo //bar to foo/BUILD bar/BUILD.bazel (whichever exist)
    99  builds() {
   100    for i in "${@}"; do
   101      echo $(ls ${i:2}/{BUILD,BUILD.bazel} 2>/dev/null)
   102    done
   103  }
   104  
   105  # Remove lines with //something:all-srcs from files
   106  # Usage:
   107  #   remove-all-srcs <targets-to-remove> <remove-from-packages>
   108  remove-all-srcs() {
   109    for b in $1; do
   110      $SED -i -e "\|${b}:all-srcs|d" $(builds $2)
   111    done
   112  }
   113  
   114  # Global variable to track when we are finished
   115  remove_unused_go_libraries_finished=
   116  # Remove every go_library() target from workspace with no one depending on it.
   117  remove-unused-go-libraries() {
   118    local libraries deps
   119    deps="$(unused-go-libraries)"
   120    if [[ -z "$deps" ]]; then
   121      echo "All remaining go libraries are alive" >&2
   122      remove_unused_go_libraries_finished=true
   123      return 0
   124    fi
   125    echo "Unused libraries:" >&2
   126    for d in $deps; do
   127      echo "  DEAD: $d" >&2
   128    done
   129    if [[ "$1" == "--check" || "$1" != "--fix" ]]; then
   130      echo "Correct with $0 --fix" >&2
   131      exit 1
   132    else
   133      echo Cleaning up unused dependencies... >&2
   134    fi
   135    local unused_packs unused_files all_srcs_packs
   136    unused_packs=$(packages $deps)
   137    unused_files=$(sources $deps)
   138    # Packages with //unused-package:all-srcs references
   139    all_srcs_packs=$(all-srcs-refs $unused_packs)
   140  
   141    pushd "$(dirname ${BASH_SOURCE})/.."
   142    remove-all-srcs "$unused_packs" "$all_srcs_packs"
   143    rm -f $unused_files $(builds $unused_packs)
   144    popd
   145  }
   146  
   147  # Continue until we do not remove anything
   148  while [[ -z $remove_unused_go_libraries_finished ]]; do
   149    remove-unused-go-libraries "${1:-}"
   150  done