diff options
| author | Mike McQuaid | 2012-03-18 15:33:21 +1300 | 
|---|---|---|
| committer | Mike McQuaid | 2012-03-18 15:34:41 +1300 | 
| commit | b27b761931b987b9dd8a9fc080bbf35270af7cca (patch) | |
| tree | fc4adbbfcf47fa8eba4f011630037f461cc5162c /Library/Contributions/cmds | |
| parent | d2ad0d02326634d5ff9b92899b60190271e45786 (diff) | |
| download | homebrew-b27b761931b987b9dd8a9fc080bbf35270af7cca.tar.bz2 | |
Rename external commands directory from examples.
Fixes #10829.
Diffstat (limited to 'Library/Contributions/cmds')
| -rwxr-xr-x | Library/Contributions/cmds/brew-beer.rb | 179 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-dirty.rb | 7 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-graph | 311 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-grep | 3 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-leaves.rb | 27 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-linkapps.rb | 31 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-man | 51 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-mirror-check.rb | 55 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-missing.rb | 37 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-pull.rb | 78 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-readall.rb | 14 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-server | 208 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-switch.rb | 40 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-unpack.rb | 93 | ||||
| -rwxr-xr-x | Library/Contributions/cmds/brew-which.rb | 49 | 
15 files changed, 1183 insertions, 0 deletions
diff --git a/Library/Contributions/cmds/brew-beer.rb b/Library/Contributions/cmds/brew-beer.rb new file mode 100755 index 000000000..4ce1f9b9d --- /dev/null +++ b/Library/Contributions/cmds/brew-beer.rb @@ -0,0 +1,179 @@ +HOMEBREW_BEER = <<-EOS +Recipe stolen from: http://allrecipes.com/howto/beer-brewing-for-beginners/ + +**The Key Ingredients** +Before beginning the brewing process, you must first understand the four key +ingredients necessary to brew a batch of beer: water, fermentable sugar, hops, +and yeast. Each ingredient is integral to the recipe and must be cooked in a +certain way to yield a successful batch of brew. Understanding their basic +qualities and how each ingredient is meant to react with the others is an +important aspect of beer brewing. + +Water: Water is the primary ingredient in beer, so it is very important the +water tastes good. If the tap water at your house tastes good to you, then it +is fine to use for beer brewing. If you don't like the way your tap water +tastes, then you can use bottled or distilled water instead. If you use tap +water, boil it first to evaporate the chlorine and other chemicals that may +interfere with the brewing process. Let the water cool before using. + +Fermented Sugar: Malted barley is the ingredient commonly used to fill the +sugar quota in a home brew recipe. Some brewers will substitute a percentage +of corn, rice, wheat, or other grains to add a lighter flavor to the beer. +Beginning brewers should purchase a ready-to-use form of malted barley called +malt syrup or malt extract, rather than attempting to malt the grain from +scratch, as it is a very complex and touchy process. Using a malt extract will +guarantee the fermented sugar is prepared in just the right manner and will +act as it needs to throughout the beer brewing process. + +Hops: Hops are cone-like flowers found on a hop vine. They lend the bitter +flavor to beer that balances out sweetness. Hops also inhibit spoilage and +help keep the "head" (the frothy top when a beer is poured) around longer. + +Yeast: First things first: Do not use bread yeast for beer brewing! Beer yeast +is cultivated especially for use in brewing. There are two broad categories of +beer yeast: ale and lager. Ale yeasts are top-fermenting, which means they +tend to hang out at the top of the carboy while fermenting and rest at the +bottom after the majority of fermenting has occurred. Ale yeasts will not +actively ferment below 50 degrees F (20 degrees C). Lager yeasts are +bottom-fermenters and are best used at a temperature ranging from 55 degrees F +(25 degrees C) down to 32 degrees F (0 degrees C). As their names suggest, the +type of yeast used plays an important part in influencing the type of beer +that will be made. Do not rely on the yeast to define the beer, however, as +all of the ingredients play a part in the taste and type of beer you will +create. + +**Ready to Brew?** +We've opted to use a simple ale recipe to guide you through the process. The +first cooking step in brewing is to make the wort, a soupy mixture of malt and +sugar that is boiled before fermentation. Malt and sugar form the perfect food +for yeast to grown in--thus making the all-important process of fermentation +possible. All of the ingredients for beer-making can be found at your local +brew supply store, or at any number of beer outfitters. Once you've got all +the necessary equipment and ingredients, you're ready to begin the beer-making +process by properly sanitizing your equipment, making and cooling the wort, +fermenting the wort, and bottling your brew. + +Ingredients: + +1.5 gallons water +6 pounds canned pre-hopped light malt syrup +1 ounce hop pellets (choose your flavor) +Ice poured into a water bath (do not use store-bought ice) +3 gallons cool water +2 (7-gram) packets ale yeast +1 cup warm water (about 90 degrees F or 35 degrees C) +3/4 cup liquid corn syrup (or 4 ounces dry corn syrup) +1 (4-ounce) container iodine solution +1 tablespoon bleach + +A bottle of household bleach or an iodine solution that can be bought at your +local home brew shop to sanitize all of your materials or use will be +necessary. (Make a bleach disinfecting solution with 1 tablespoon bleach to 1 +gallon water.) Be sure to rinse the equipment well with boiling water before +using it. + +Part I: Make and Cool the Wort + +Sanitize the pot, stirring spoon and fermenter with the sanitizing solution. +Rinse everything in boiling water. + +Bring 1.5 gallons of water to a boil. When the water begins to boil, remove it +from the heat and stir in the malt syrup until it dissolves. Do not allow any +syrup to stick to the bottom or sides of the pot, as it will burn and taste +awful. Return the pot to the heat and bring the mixture to a boil for 50 +minutes, stir frequently and watch constantly to prevent boil-overs. If the +mixture threatens to boil over, reduce the heat. + +After 50 minutes have elapsed, stir in the hop pellets. Hops will create a +foam on the top of the liquid--so if the pot is very full, the hops may cause +a boil-over. You want to avoid this at all costs by lowering the heat or +spraying the foam down with a water bottle (sanitized, of course). Let the +hops cook for 10 to 20 minutes. + +While the wort is being made, prep the yeast by placing 1 packet of yeast in 1 +cup of warm water (90 degrees F or 35 degrees C; stir and cover for 10 +minutes. If the yeast does not react (form foam), discard the yeast solution +and try again with the second yeast packet. + +At about the time hops are added to the wort, you should prepare an ice-cold +water bath in either a large sink or tub to quick-cool the wort. Once the wort +is finished cooking, float the pot in the water bath. Stir the wort while it +is sitting in the bath so that the maximum amount of wort reaches the pot's +sides where it can cool quickly. If the water bath heats up, add more ice to +keep the water bath cold. It should take approximately 20 minutes to cool the +wort to approximately 80 degrees F (27 degrees C). + + +Part II: Ferment + +Pour the 3 gallons cool water into your sanitized carboy. Funnel in the warm +wort. Sprinkle the prepared yeast into the carboy. Cover the carboy's mouth +with plastic wrap and cap it with a lid. Holding your hand tight over the lid, +shake the bottle up and down to distribute the yeast. Remove the plastic wrap, +wipe any wort around the carboy's mouth off and place the fermentation lock +(with a little water added into its top) on. + +Store the carboy in a cool (60 to 75 degrees F or 15 to 24 degrees C) safe +place without direct sunlight where you will be able to easily clean up or +drain any foam that escapes. A bathtub is an excellent place to store your +fermenter if there are no windows in the room. If the temperature in the +storage room drops and bubbling in the carboy's airlock stops, move the carboy +to a warmer room. The fermenting will resume. Fermentation should begin within +24 hours. A clear sign of fermentation is the production of foam and air +bubbles in the fermentation lock. + +When fermentation begins, it produces a slow trickle of bubbles that will +increase in amount for a few days, and then reduce to a slow trickle again. +Let the beer ferment for approximately 14 days when the primary fermentation +has taken place. If the fermenting process pops the fermentation lock out of +the carboy, re-sanitize it and place it back into the carboy. + + +Part III: Bottle + +Sanitize all of your bottles by soaking them in the sanitizing solution (make +sure to hold them under the solution so the water gets inside of the bottles) +for 1 hour. Rinse the bottles with boiling water. Also sanitize a small +cooking pot, bottling bucket, siphon and racking cane. Follow the instructions +that came with the bottle caps to sanitize them. Let everything air dry. +Combine the corn syrup and 1 cup water in the sanitized cooking pot. Let boil +10 minutes. Pour mixture into the bottling bucket. Be careful not to add too +much corn syrup to the bottling bucket, because this will over-carbonate the +beer and cause bottles to explode! Place the fermenter full of beer on the +kitchen counter and the bottling bucket on the ground below it. Attach the +racking cane to the siphon. Prepare the siphon by filling it with tap water. +Pinch both ends of the siphon to prevent the water from running out. Place one +end of the racking cane and siphon into the iodine solution and one end into +an empty jar. When the solution has run into the siphon and expelled all of +the water into the jar, pinch both ends and let the iodine sit in the siphon +for 5 minutes to re-sanitize the siphon. (Resist the temptation to blow into +the siphon with your mouth to encourage the flow of iodine solution.) + +Place one end of the sanitized siphon into the fermenter and the other end +into the jar; once the beer has begun flowing through the siphon, transfer its +end to the bottling bucket. Monitor the speed that the beer transfers into the +bottling bucket by pinching and releasing the siphon with your fingers (or use +a specialty clamp). The beer should not splash into the bucket; it should +gently rush into it. Once all of the beer has been siphoned into the bucket, +cover it (with a sanitized cover ) and wait 30 minutes for the sediment to +settle at the bottom of the bucket. + +Place the bottling bucket on the counter, attach the siphon and run the other +end of the siphon into a bottle. Fill each bottle with beer to 3/4 inch from +the top of the bottle. Cap each bottle with the bottle-capper. Check and +double-check that the caps are secure. Sure Signs of Infection: + +Keep your eyes peeled for strands of slime in the beer and a milky layer at +the top and/or residue bumps clinging to the air space in the bottleneck. If +the beer has strands, it most likely has a lacto infection and should be +discarded. The milky layer is a sign of a micro-derm infection; this beer +should also be discarded. + +Age the bottles at room temperature for up to two months, but for at least two +weeks, before cracking one open, proposing a toast to yourself and impressing +your friends! Ready to expand your brewing prowess? + +Thanks for brewin' +EOS + +puts HOMEBREW_BEER diff --git a/Library/Contributions/cmds/brew-dirty.rb b/Library/Contributions/cmds/brew-dirty.rb new file mode 100755 index 000000000..e22ad75c6 --- /dev/null +++ b/Library/Contributions/cmds/brew-dirty.rb @@ -0,0 +1,7 @@ +# See: http://github.com/mxcl/homebrew/issues/issue/1359 + +to_list = HOMEBREW_CELLAR.children.select { |pn| pn.directory? } +to_list.each do |d| +  versions = d.children.select { |pn| pn.directory? }.collect { |pn| pn.basename.to_s } +  puts "#{d.basename} (#{versions.join(', ')})" if versions.size > 1 +end diff --git a/Library/Contributions/cmds/brew-graph b/Library/Contributions/cmds/brew-graph new file mode 100755 index 000000000..27c80af83 --- /dev/null +++ b/Library/Contributions/cmds/brew-graph @@ -0,0 +1,311 @@ +#!/usr/bin/env python +""" +$ brew install graphviz +$ brew graph | dot -Tsvg -ohomebrew.svg +$ open homebrew.svg +""" +from __future__ import with_statement + +from contextlib import contextmanager +import re +from subprocess import Popen, PIPE +import sys + + +def run(command, print_command=False): +    "Run a command, returning the exit code and output." +    if print_command: print command +    p = Popen(command, stdout=PIPE) +    output, errput = p.communicate() +    return p.returncode, output + + +def _quote_id(id): +    return '"' + id.replace('"', '\"') + '"' + + +def format_attribs(attrib): +    if len(attrib) == 0: +        return '' + +    values = ['%s="%s"' % (k, attrib[k]) for k in attrib] +    return '[' + ','.join(values) + ']' + + +class Output(object): +    def __init__(self, fd=sys.stdout, tabstyle="  "): +        self.fd = fd +        self.tabstyle = tabstyle +        self.tablevel = 0 + +    def close(self): +        self.fd = None + +    def out(self, s): +        self.tabout() +        self.fd.write(s) + +    def outln(self, s=None): +        if s is not None: +            self.tabout() +            self.fd.write(s) +        self.fd.write('\n') + +    @contextmanager +    def indented(self): +        self.indent() +        yield self +        self.dedent() + +    def indent(self): +        self.tablevel += 1 + +    def dedent(self): +        if self.tablevel == 0: +            raise Exception('No existing indent level.') +        self.tablevel -= 1 + +    def tabout(self): +        if self.tablevel: +            self.fd.write(self.tabstyle * self.tablevel) + + +class NodeContainer(object): +    def __init__(self): +        self.nodes = list() +        self.node_defaults = dict() +        # Stack of node attribs +        self._node_styles = list() + +    def _node_style(self): +        if (len(self._node_styles) > 0): +            return self._node_styles[-1] +        else: +            return dict() + +    def _push_node_style(self, attrib): +        self._node_styles.append(attrib) + +    def _pop_node_style(self): +        return self._node_styles.pop() + +    @contextmanager +    def node_styles(self, attrib): +        self._push_node_style(attrib) +        yield +        self._pop_node_style() + +    def node(self, nodeid, label, attrib=None): +        _attrib = dict(self._node_style()) +        if attrib is not None: +            _attrib.update(attrib) + +        n = Node(nodeid, label, _attrib) +        self.nodes.append(n) +        return n + +    def nodes_to_dot(self, out): +        if len(self.node_defaults) > 0: +            out.outln("node " + format_attribs(self.node_defaults) + ";") + +        if len(self.nodes) == 0: +            return + +        id_width = max([len(_quote_id(n.id)) for n in self.nodes]) +        for node in self.nodes: +            node.to_dot(out, id_width) + + +class Node(object): +    def __init__(self, nodeid, label, attrib=None): +        self.id = nodeid +        self.label = label +        self.attrib = attrib if attrib is not None else dict() + +    def as_dot(self, id_width=1): +        _attribs = dict(self.attrib) +        _attribs['label'] = self.label + +        return '%-*s %s' % (id_width, _quote_id(self.id), format_attribs(_attribs)) + + +    def to_dot(self, out, id_width=1): +        out.outln(self.as_dot(id_width)) + + +class ClusterContainer(object): +    def __init__(self): +        self.clusters = list() + +    def cluster(self, clusterid, label, attrib=None): +        c = Cluster(clusterid, label, self, attrib) +        self.clusters.append(c) +        return c + + +class Cluster(NodeContainer, ClusterContainer): +    def __init__(self, clusterid, label, parentcluster=None, attrib=None): +        NodeContainer.__init__(self) +        ClusterContainer.__init__(self) + +        self.id = clusterid +        self.label = label +        self.attrib = attrib if attrib is not None else dict() +        self.parentcluster = parentcluster + +    def cluster_id(self): +        return _quote_id("cluster_" + self.id) + +    def to_dot(self, out): +        out.outln("subgraph %s {" % self.cluster_id()) +        with out.indented(): +            out.outln('label = "%s"' % self.label) +            for k in self.attrib: +                out.outln('%s = "%s"' % (k, self.attrib[k])) + +            for cluster in self.clusters: +                cluster.to_dot(out) + +            self.nodes_to_dot(out) +        out.outln("}") + + +class Edge(object): +    def __init__(self, source, target, attrib=None): +        if attrib is None: +            attrib = dict() + +        self.source = source +        self.target = target +        self.attrib = attrib + +    def to_dot(self, out): +        out.outln(self.as_dot()) + +    def as_dot(self): +        return " ".join((_quote_id(self.source), "->", _quote_id(self.target), format_attribs(self.attrib))) + + +class EdgeContainer(object): +    def __init__(self): +        self.edges = list() +        self.edge_defaults = dict() +        # Stack of edge attribs +        self._edge_styles = list() + +    def _edge_style(self): +        if (len(self._edge_styles) > 0): +            return self._edge_styles[-1] +        else: +            return dict() + +    def _push_edge_style(self, attrib): +        self._edge_styles.append(attrib) + +    def _pop_edge_style(self): +        return self._edge_styles.pop() + +    @contextmanager +    def edge_styles(self, attrib): +        self._push_edge_style(attrib) +        yield +        self._pop_edge_style() + +    def link(self, source, target, attrib=None): +        _attrib = dict(self._edge_style()) +        if attrib is not None: +            _attrib.update(attrib) + +        e = Edge(source, target, _attrib) +        self.edges.append(e) +        return e + +    def edges_to_dot(self, out): +        if len(self.edge_defaults) > 0: +            out.outln("edge " + format_attribs(self.edge_defaults) + ";") + +        if len(self.edges) == 0: +            return + +        for edge in self.edges: +            edge.to_dot(out) + + +class Graph(NodeContainer, EdgeContainer, ClusterContainer): +    """ +    Contains the nodes, edges, and subgraph definitions for a graph to be +    turned into a Graphviz DOT file. +    """ + +    def __init__(self, label=None, attrib=None): +        NodeContainer.__init__(self) +        EdgeContainer.__init__(self) +        ClusterContainer.__init__(self) + +        self.label = label if label is not None else "Default Label" +        self.attrib = attrib if attrib is not None else dict() + +    def dot(self, fd=sys.stdout): +        try: +            self.o = Output(fd) +            self._dot() +        finally: +            self.o.close() + +    def _dot(self): +        self.o.outln("digraph G {") + +        with self.o.indented(): +            self.o.outln('label = "%s"' % self.label) +            for k in self.attrib: +                self.o.outln('%s = "%s"' % (k, self.attrib[k])) + +            self.nodes_to_dot(self.o) + +            for cluster in self.clusters: +                self.o.outln() +                cluster.to_dot(self.o) + +            self.o.outln() +            self.edges_to_dot(self.o) + +        self.o.outln("}") + + +def main(): +    cmd = ["brew", "deps"] +    cmd.extend(sys.argv[1:] or ["--all"]) +    code, output = run(cmd) +    output = output.strip() +    depgraph = list() + +    for f in output.split("\n"): +        stuff = f.split(":",2) +        name = stuff[0] +        deps = stuff[1].strip() +        if not deps: +            deps = list() +        else: +            deps = deps.split(" ") +        depgraph.append((name, deps)) + +    hb = Graph("Homebrew Dependencies", attrib={'labelloc':'b', 'rankdir':'LR', 'ranksep':'5'}) + +    used = set() +    for f in depgraph: +        for d in f[1]: +            used.add(f[0]) +            used.add(d) + +    for f in depgraph: +        if f[0] not in used: +            continue +        n = hb.node(f[0], f[0]) +        for d in f[1]: +            hb.link(d, f[0]) + +    hb.dot() + + +if __name__ == "__main__": +    main() diff --git a/Library/Contributions/cmds/brew-grep b/Library/Contributions/cmds/brew-grep new file mode 100755 index 000000000..027f97c4c --- /dev/null +++ b/Library/Contributions/cmds/brew-grep @@ -0,0 +1,3 @@ +#!/bin/bash + +grep $@ $HOMEBREW_REPOSITORY/Library/Formula/* diff --git a/Library/Contributions/cmds/brew-leaves.rb b/Library/Contributions/cmds/brew-leaves.rb new file mode 100755 index 000000000..d24709229 --- /dev/null +++ b/Library/Contributions/cmds/brew-leaves.rb @@ -0,0 +1,27 @@ +# Outputs formulas that are installed but are not a dependency for +# any other installed formula. +# See: http://github.com/mxcl/homebrew/issues/issue/1438 + +require 'formula' + +def get_used_by +  used_by = {} +  Formula.all.each do |f| +    next if f.deps == nil + +    f.deps.each do |dep| +      _deps = used_by[dep] || [] +      _deps << f.name unless _deps.include? f.name +      used_by[dep] = _deps +    end +  end + +  return used_by +end + +deps_graph = get_used_by() +installed = HOMEBREW_CELLAR.children.select { |pn| pn.directory? }.collect { |pn| pn.basename.to_s } +installed.each do |name| +  deps = deps_graph[name] || [] +  puts name unless deps.any? { |dep| installed.include? dep } +end diff --git a/Library/Contributions/cmds/brew-linkapps.rb b/Library/Contributions/cmds/brew-linkapps.rb new file mode 100755 index 000000000..5a36bb4d1 --- /dev/null +++ b/Library/Contributions/cmds/brew-linkapps.rb @@ -0,0 +1,31 @@ +# Links any Applications (.app) found in installed prefixes to ~/Applications +require "formula" + +HOME_APPS = File.expand_path("~/Applications") + +unless File.exist? HOME_APPS +  opoo "#{HOME_APPS} does not exist, stopping." +  puts "Run `mkdir ~/Applications` first." +  exit 1 +end + +HOMEBREW_CELLAR.subdirs.each do |keg| +  next unless keg.subdirs +  name = keg.basename.to_s + +  if ((f = Formula.factory(name)).installed? rescue false) +    Dir["#{f.installed_prefix}/*.app", "#{f.installed_prefix}/bin/*.app", "#{f.installed_prefix}/libexec/*.app"].each do |p| +      puts "Linking #{p}" +      appname = File.basename(p) +      target = HOME_APPS+"/"+appname +      if File.exist? target +        if File.symlink? target +          system "rm", target +        else +          onoe "#{target} already exists, skipping." +        end +      end +      system "ln", "-s", p, HOME_APPS +    end +  end +end diff --git a/Library/Contributions/cmds/brew-man b/Library/Contributions/cmds/brew-man new file mode 100755 index 000000000..8afe2029d --- /dev/null +++ b/Library/Contributions/cmds/brew-man @@ -0,0 +1,51 @@ +#!/bin/bash + +set -e +shopt -s nullglob + +SOURCE_PATH="$HOMEBREW_REPOSITORY/Library/Contributions/manpages" +TARGET_PATH="$HOMEBREW_REPOSITORY/share/man/man1" +LINKED_PATH="$HOMEBREW_PREFIX/share/man/man1" + + +die (){ +    echo $1 +    exit 1 +} + +test "$1" = '--link' || \ +test "$1" = '-l' && { +  [[ $TARGET_PATH == $LINKED_PATH ]] && exit 0 + +  for page in "$TARGET_PATH"/*.1 +  do +    ln -s $page $LINKED_PATH +  done +  exit 0 +} + +/usr/bin/which -s ronn || die "You need to \"gem install ronn\" and put it in your path." + +test "$1" = '--server' || \ +test "$1" = '-s' && { +  echo "Man page test server: http://localhost:1207/" +  echo "Control-C to exit." +  ronn --server $SOURCE_PATH/* +  exit 0 +} + +echo "Writing manpages to $TARGET_PATH" + +for i in "$SOURCE_PATH"/*.md +do +  # Get the filename only, without the .md extension +  j=`basename $i` +  target_file="$TARGET_PATH/${j%\.md}" + +  ronn --roff --pipe --organization='Homebrew' --manual='brew' $i > $target_file +done + +if test "$1" = '--verbose' || test "$1" = '-v' +then +  man brew +fi diff --git a/Library/Contributions/cmds/brew-mirror-check.rb b/Library/Contributions/cmds/brew-mirror-check.rb new file mode 100755 index 000000000..1ae06ce6a --- /dev/null +++ b/Library/Contributions/cmds/brew-mirror-check.rb @@ -0,0 +1,55 @@ +require 'formula' + +class Formula +  def test_mirror mirror +    url, specs = mirror.values_at :url, :specs +    downloader = download_strategy.new url, name, version, specs + +    # Force the downloader to attempt the download by removing the tarball if +    # it is allready cached. +    tarball_path = downloader.tarball_path +    tarball_path.unlink if tarball_path.exist? + +    begin +      fetched = downloader.fetch +    rescue DownloadError => e +      opoo "Failed to fetch from URL: #{url}" +      return +    end + +    verify_download_integrity fetched if fetched.kind_of? Pathname +  end +end + +module Homebrew extend self +  def check_mirrors +    mirror_check_usage = <<-EOS +Usage: brew mirror-check <formulae ...> + +Cycle through mirror lists for each formula, attempt a download and validate +MD5 sums. +    EOS + +    if ARGV.empty? +      puts mirror_check_usage +      exit 0 +    end + +    formulae = ARGV.formulae +    raise FormulaUnspecifiedError if formulae.empty? + +    formulae.each do |f| +      if f.mirrors.empty? +        opoo "#{f.name} has no mirrors" +        next +      else +        oh1 "Testing mirrors for #{f.name}" +        f.mirrors.each{ |m| f.test_mirror m } +      end +    end +  end +end + +# Here is the actual code that gets run when `brew` loads this external +# command. +Homebrew.check_mirrors diff --git a/Library/Contributions/cmds/brew-missing.rb b/Library/Contributions/cmds/brew-missing.rb new file mode 100755 index 000000000..50fae12e4 --- /dev/null +++ b/Library/Contributions/cmds/brew-missing.rb @@ -0,0 +1,37 @@ +require "formula" +require "cmd/outdated" + +def installed_brews +  formulae = [] +  HOMEBREW_CELLAR.subdirs.each do |rack| +    f = Formula.factory rack.basename.to_s rescue nil +    formulae << f if f and f.installed? +  end +  formulae +end + +def main +  return unless HOMEBREW_CELLAR.exist? + +  # Names of outdated brews; they count as installed. +  outdated = Homebrew.outdated_brews.collect{ |b| b.name } + +  formulae_to_check = if ARGV.named.empty? +    installed_brews +  else +    ARGV.formulae +  end + +  formulae_to_check.each do |f| +    missing_deps = f.recursive_deps.map{ |g| g.name }.uniq.reject do |dep_name| +      Formula.factory(dep_name).installed? or outdated.include?(dep_name) +    end + +    unless missing_deps.empty? +      print "#{f.name}: " if formulae_to_check.size > 1 +      puts "#{missing_deps * ' '}" +    end +  end +end + +main() diff --git a/Library/Contributions/cmds/brew-pull.rb b/Library/Contributions/cmds/brew-pull.rb new file mode 100755 index 000000000..30d04120b --- /dev/null +++ b/Library/Contributions/cmds/brew-pull.rb @@ -0,0 +1,78 @@ +# Gets a patch from a GitHub commit or pull request and applies it to Homebrew. +# Optionally, installs it too. + +require 'utils.rb' + +if ARGV.include? '--install' +  ARGV.delete '--install' +  install = true +end + +if ARGV.empty? +  onoe 'This command requires at least one argument containing a URL or pull request number' +end + +HOMEBREW_REPOSITORY.cd do +  ARGV.named.each do|arg| +    if arg.to_i > 0 +      url = 'https://github.com/mxcl/homebrew/pull/' + arg + '.patch' +    else +      # This regex should work, if it's too precise, feel free to fix it. +      urlmatch = arg.match 'https:\/\/github.com\/\w+\/homebrew\/(pull\/(\d+)|commit\/\w{4,40})' +      if !urlmatch +        ohai 'Ignoring URL:', "Not a GitHub pull request or commit: #{arg}" +        next +      end + +      # GitHub provides commits'/pull-requests' raw patches using this URL. +      url = urlmatch[0] + '.patch' +    end + +    # The cache directory seems like a good place to put patches. +    HOMEBREW_CACHE.mkpath +    patchpath = (HOMEBREW_CACHE+File.basename(url)) +    curl url, '-o', patchpath + +    # Store current revision +    revision = `git log -n1 --format=%H`.strip() + +    ohai 'Applying patch' +    patch_args = %w[am --signoff] +    # Normally we don't want whitespace errors, but squashing them can break +    # patches so an option is provided to skip this step. +    patch_args << '--whitespace=fix' unless ARGV.include? '--ignore-whitespace' +    patch_args << patchpath + +    safe_system 'git', *patch_args + +    issue = arg.to_i > 0 ? arg.to_i : urlmatch[2] +    if issue +      ohai "Patch closes issue ##{issue}" +      message = `git log HEAD^.. --format=%B` + +      # If this is a pull request, append a close message. +      if !message.include? 'Closes #' +        issueline = "Closes ##{issue}." +        signed = 'Signed-off-by:' +        message = message.gsub signed, issueline + "\n\n" + signed +        safe_system 'git', 'commit', '--amend', '-q', '-m', message +      end +    end + +    ohai 'Patch changed:' +    safe_system 'git', 'diff', "#{revision}..", '--stat' + +    if install +      `git diff #{revision}.. --name-status`.each_line do |line| +        status, filename = line.split() +        # Don't try and do anything to removed files. +        if (status == 'A' or status == 'M') and filename.include? '/Formula/' +          formula = File.basename(filename, '.rb') +          ohai "Installing #{formula}" +          # Not sure if this is the best way to install? +          safe_system 'brew', 'install', '--force', '--build-bottle', formula +        end +      end +    end +  end +end diff --git a/Library/Contributions/cmds/brew-readall.rb b/Library/Contributions/cmds/brew-readall.rb new file mode 100755 index 000000000..d04de565d --- /dev/null +++ b/Library/Contributions/cmds/brew-readall.rb @@ -0,0 +1,14 @@ +# `brew readall` tries to import all formulae one-by-one. +# This can be useful for debugging issues across all formulae +# when making significant changes to formula.rb, +# or to determine if any current formulae have Ruby issues + +require 'formula' +Formula.names.each do |n| +  begin +    f = Formula.factory(n) +  rescue Exception => e +    onoe "problem in #{Formula.path(n)}" +    puts e +  end +end diff --git a/Library/Contributions/cmds/brew-server b/Library/Contributions/cmds/brew-server new file mode 100755 index 000000000..bcc15c257 --- /dev/null +++ b/Library/Contributions/cmds/brew-server @@ -0,0 +1,208 @@ +#!/usr/bin/ruby + +## brew server: Run a local webserver for browsing available and installed brews. +# Note: this external command is ruby, but set up as a shell script, so that it gets exec'd. +# This is required for sinatra's run-loop to take over. + +$:.unshift(ENV['HOMEBREW_LIBRARY_PATH']) + +require 'global' +require 'formula' + +require 'rubygems' + +begin +  require 'sinatra' +rescue LoadError +  onoe 'Sinatra required but not found' +  puts 'To install: /usr/bin/gem install sinatra' +  exit 1 +end + +require 'cgi' + + +def link_to_formula name +  "<a href=\"/formula/#{CGI.escape(name)}\">#{name}</a>" +end + +def css_style +  "" # No CSS defined yet. +end + +def search_form +  <<-EOS +    <form action="/search"> +      Search: <input name="q" type="text"> <input type="submit"> +    </form> +  EOS +end + +def html_page +  body = <<-HTML +  <html> +    <head> +      <title>Homebrew Menu</title> +      #{css_style} +    </head> +    <body> +      <div id="wrap"> +  			<div id="header"> +  				<h1><a href="./">Homebrew</a></h1> +  				<p id="subtitle"><strong>The missing package manager for OS X</strong></p> +                                <p id="installed"><a href="/installed">Show installed packages</a></p> +  			</div> + +  			<div id="informations"> +  HTML +  yield body +  body += <<-HTML +        </div> +      </div> +    </body> +  </html> +  HTML +  return body +end + +get '/' do +  return html_page do |s| +    s << <<-HTML +    <div class="row">#{search_form}</div> +    <div class="row"> +      <ul> +    HTML +    Formula.names do |name| +      s << "<li>#{link_to_formula(name)}</li>" +    end +    s << <<-HTML +      </ul> +    </div> +    HTML +  end +end + +get '/search' do +  q = params['q'] +  results = search_brews(q) + +  s = <<-HTML +    <html> +    <head> +      <title>Search Results</title> +      #{css_style} +    </head> +    <body> +    <h1>Results</h1> +    #{search_form} +    <h4>Searched for “#{q}”</h4> +    <ul> +  HTML + +  results.each do |name| +    s << "<li>#{link_to_formula(name)}</li>" +  end + +  s += <<-HTML +    </ul> +    </body> +  </html> +  HTML + +  return s +end + +get '/formula/:name' do +  klass = Formula.factory(params[:name]) + +  installed = klass.installed? ? "Installed at" : "Not installed." +  installed_dd = klass.installed? ? "<a href=\"file://#{klass.prefix}\">#{klass.prefix}</a>" : "" + +  s = "" +  s << <<-HTML +    <html> +      <head> +        <title>Formula: #{klass.name}</title> +        #{css_style} +      </head> +      <body> +        <div>← <a href="/">Back to menu</a></div> +        <h1>#{klass.name}</h1> +        <dl> +          <dt>Version</dt> +            <dd>#{klass.version}</dd> + +          <dt>Homepage</dt> +            <dd><a href="#{klass.homepage}">#{klass.homepage}</a></dd> + +          <dt>Download</dt> +            <dd><a href="#{klass.url}">#{klass.url}</a></dd> + +          <dt>#{installed}</dt> +            <dd>#{installed_dd}</dd> +  HTML + +  unless klass.deps.count == 0 +    s << <<-HTML +            <dt>Depends on</td> +    HTML +    klass.deps.each do |dep| +      s << "<dd>#{link_to_formula(dep.name)}</dd>" +    end +  end + +  used_by = Formula.all.select{|ff| ff.deps.include?(klass.name)}.map{|f| f.name}.flatten.uniq.sort +  unless used_by.empty? +    s << <<-HTML +            <dt>Used by</td> +    HTML +    if used_by != nil +      used_by.each do |name| +        s << "<dd>#{link_to_formula(name)}</dd>" +      end +    end +  end + +  s += <<-HTML +        </dl> +      </body> +    </html> +  HTML + +  return s +end + + +def installed_formulas +  Formula.all.select{|formula| formula.installed?} +end + +get '/installed' do + +  s = <<-HTML +    <html> +    <head> +      <title>Installed Formulas</title> +      #{css_style} +    </head> +    <body> +     <h1>Installed Fomulas</h1> +    <ul> +  HTML + +  installed_formulas.each do |formula| +    s << "<li>#{link_to_formula(formula.name)}</li>" +  end + +  s += <<-HTML +    </ul> +    <div>← <a href="/">Back to menu</a></div> +    </body> +  </html> +  HTML + +  return s +end + + +puts "View our tasting menu at http://localhost:4567/\nUse \"Control-C\" to exit.\n\n" diff --git a/Library/Contributions/cmds/brew-switch.rb b/Library/Contributions/cmds/brew-switch.rb new file mode 100755 index 000000000..3b51f941c --- /dev/null +++ b/Library/Contributions/cmds/brew-switch.rb @@ -0,0 +1,40 @@ +require 'formula' +require 'keg' + +if ARGV.named.length != 2 +  onoe "Usage: brew switch <formula> <version>" +  exit 1 +end + +name = ARGV.shift +version = ARGV.shift + +# Does this formula have any versions? +f = Formula.factory(name.downcase) +cellar = f.prefix.parent +unless cellar.directory? +  onoe "#{name} not found in the Cellar." +  exit 2 +end + +# Does the target version exist? +unless (cellar+version).directory? +  onoe "#{name} does not have a version \"#{version}\" in the Cellar." + +  versions = cellar.children.select { |pn| pn.directory? }.collect { |pn| pn.basename.to_s } +  puts "Versions available: #{versions.join(', ')}" + +  exit 3 +end + +# Unlink all existing versions +cellar.children.select { |pn| pn.directory? }.each do |v| +  keg = Keg.new(v) +  puts "Cleaning #{keg}" +  keg.unlink +end + +# Link new version + +keg = Keg.new(cellar+version) +puts "#{keg.link} links created for #{keg}"
\ No newline at end of file diff --git a/Library/Contributions/cmds/brew-unpack.rb b/Library/Contributions/cmds/brew-unpack.rb new file mode 100755 index 000000000..d4d72623e --- /dev/null +++ b/Library/Contributions/cmds/brew-unpack.rb @@ -0,0 +1,93 @@ +require 'formula' + +require 'stringio' +module ScriptDataReader +  # This module contains a method for extracting the contents of DATA from a +  # Ruby file other than the script containing the currently executing +  # function.  Many thanks to Glenn Jackman's Stackoverflow answer which +  # provided this code: +  # +  #   http://stackoverflow.com/questions/2156629/can-i-access-the-data-from-a-required-script-in-ruby/2157556#2157556 +  def self.load(filename) +    data = StringIO.new +    File.open(filename) do |f| +      begin +        line = f.gets +      end until line.nil? or line.match(/^__END__$/) +      while line = f.gets +        data << line +      end +    end +    data.rewind +    data +  end +end + +# Need to tweak the Formula class slightly so that patching is option and `DATA` +# patches work correctly. +class Formula +  # Create a reference to the original Formula.patch method and then override +  # so that paching only happens if the user asks. +  alias do_patch patch +  def patch +    if ARGV.include? '--patch' +      # Yes Ruby, we are about to redefine a constant. Just breathe. +      orig_v = $VERBOSE; $VERBOSE = nil +      Formula.const_set 'DATA', ScriptDataReader.load(path) +      $VERBOSE = orig_v + +      do_patch +    end +  end + +  # handle_llvm_failure() requires extend/ENV, so let's never fail +  # with llvm since we don't particularly care in this context. +  def fails_with_llvm?; false; end +end + +module Homebrew extend self +  def unpack +    unpack_usage = <<-EOS +Usage: brew unpack [--patch] [--destdir=path/to/extract/in] <formulae ...> + +Unpack formulae source code for inspection. + +Formulae archives will be extracted to subfolders inside the current working +directory or a directory specified by `--destdir`. If the `--patch` option is +supplied, patches will also be downloaded and applied. +    EOS + +    if ARGV.empty? +      puts unpack_usage +      exit 0 +    end + +    formulae = ARGV.formulae +    raise FormulaUnspecifiedError if formulae.empty? + +    unpack_dir = ARGV.options_only.select {|o| o.start_with? "--destdir="} +    if unpack_dir.empty? +      unpack_dir = Pathname.new Dir.getwd +    else +      unpack_dir = Pathname.new(unpack_dir.first.split('=')[1]).realpath +      unpack_dir.mkpath unless unpack_dir.exist? +    end + +    raise "Cannot write to #{unpack_dir}" unless unpack_dir.writable? + +    formulae.each do |f| +      # Create a nice name for the stage folder. +      stage_dir = unpack_dir + [f.name, f.version].join('-') +      raise "Destination #{stage_dir} allready exists!" if stage_dir.exist? + +      f.brew do +        oh1 "Unpacking #{f.name} to: #{stage_dir}" +        cp_r Dir.getwd, stage_dir +      end +    end +  end +end + +# Here is the actual code that gets run when `brew` loads this external +# command. +Homebrew.unpack diff --git a/Library/Contributions/cmds/brew-which.rb b/Library/Contributions/cmds/brew-which.rb new file mode 100755 index 000000000..b3318ee76 --- /dev/null +++ b/Library/Contributions/cmds/brew-which.rb @@ -0,0 +1,49 @@ +require 'extend/pathname' + + +module Homebrew extend self +  def which_versions which_brews=nil +    brew_links = Array.new +    version_map = Hash.new + +    real_cellar = HOMEBREW_CELLAR.realpath + +    paths=%w[bin sbin lib].collect {|d| HOMEBREW_PREFIX+d} + +    paths.each do |path| +      path.find do |path| +        next unless path.symlink? && path.resolved_path_exists? +        brew_links << Pathname.new(path.realpath) +      end +    end + +    brew_links = brew_links.collect{|p|p.relative_path_from(real_cellar).to_s}.reject{|p|p.start_with?("../")} + +    brew_links.each do |p| +      parts = p.split("/") +      next if parts.count < 2 # Shouldn't happen for normally installed brews +      brew = parts.shift +      version = parts.shift + +      next unless which_brews.include? brew if which_brews + +      versions = version_map[brew] || [] +      versions << version unless versions.include? version +      version_map[brew] = versions +    end + +    return version_map +  end + +  def which +    which_brews = ARGV.named.empty? ? nil : ARGV.named + +    brews = which_versions which_brews +    brews.keys.sort.each do |b| +      puts "#{b}: #{brews[b].sort*' '}" +    end +    puts +  end +end + +Homebrew.which  | 
