<commit_before>#!/usr/bin/python
#- Copyright 2014 GOTO 10.
#- Licensed under the Apache License, Version 2.0 (see LICENSE).

from command import Command, shell_escape
import argparse
import node
import os
import os.path
import re
import sys


## Implements the 'makefile' command.


# An individual target within a makefile.
class MakefileTarget(object):

  def __init__(self, output, inputs, commands):
    self.output = output
    self.inputs = inputs
    self.commands = commands

  # Returns the string output path for this target.
  def get_output_path(self):
    return self.output

  # Write this target, in Makefile syntax, to the given output stream.
  def write(self, out):
    out.write("%(outpath)s: %(inpaths)s\n\t%(commands)s\n\n" % {
      "outpath": shell_escape(self.output),
      "inpaths": " ".join(map(shell_escape, self.inputs)),
      "commands": "\n\t".join(self.commands)
    })


# The contents of a complete makefile. A makefile object is meant to be dumb and
# basically only concerned with accumulating and then printing the makefile
# source. Any nontrivial logic is the responsibility of whoever is building the
# makefile object.
class Makefile(object):

  def __init__(self):
    self.targets = {}
    self.phonies = set()

  # Add a target that builds the given output from the given inputs by invoking
  # the given commands in sequence.
  def add_target(self, output, inputs, commands, is_phony):
    target = MakefileTarget(output, inputs, commands)
    self.targets[output] = target
    if is_phony:
      self.phonies.add(output)

  # Write this makefile in Makefile syntax to the given stream.
  def write(self, out):
    for name in sorted(self.targets.keys()):
      target = self.targets[name]
      target.write(out)
    # Mike Moffit says: list *all* the phonies.
    if self.phonies:
      out.write(".PHONY: %s\n\n" % " ".join(sorted(list(self.phonies))))


# A segmented name. This is sort of like a relative file path but avoids any
# ambiguities that might be caused by multiple relative paths pointing to the
# same thing and differences in path separators etc. Names compare
# lexicographically and are equal if their parts are structurally equal.
class Name(object):

  def __init__(self, parts):
    self.parts = tuple(parts)

  # Returns a new name that consists of this name followed by the given parts.
  def append(self, *subparts):
    return Name(self.parts + subparts)

  # Returns a new name that consists of the given prefix followed by this name.
  def prepend(self, *prefix):
    return Name(prefix + self.parts)

  # Returns a tuple that holds the parts of this name.
  def get_parts(self):
    return self.parts

  # Returns the last part, for instance the last part of a|b|c is "c".
  def get_last_part(self):
    return self.parts[-1]

  @staticmethod
  def of(*parts):
    return Name(parts)

  def __hash__(self):
    return ~hash(self.parts)

  def __eq__(self, that):
    return (self.parts == that.parts)

  def __cmp__(self, that):
    return cmp(self.parts, that.parts)

  def __str__(self):
    return "::".join(self.parts)

  def __repr__(self):
    return str(self)


# An abstract file wrapper that encapsulates various file operations.
class AbstractFile(object):

  def __init__(self, path, parent):
    self.path = path
    self.parent = parent
    self.children = {}
    self.attribs = {}

  # Creates a new file object of the appropriate type depending on what kind of
  # file the path points to.
  @staticmethod
  def at(path, parent=None):
    if os.path.isdir(path):
      return Folder(path, parent)
    elif os.path.isfile(path):
      return RegularFile(path, parent)
    else:
      return MissingFile(path, parent)

  # Returns the folder that contains this file.
  def get_parent(self):
    if self.parent is None:
      self.parent = AbstractFile.at(os.path.dirname(self.path))
    return self.parent<commit_msg>Fix issue when the build file is in the current directory.<commit_after>#!/usr/bin/python
#- Copyright 2014 GOTO 10.
#- Licensed under the Apache License, Version 2.0 (see LICENSE).

from command import Command, shell_escape
import argparse
import node
import os
import os.path
import re
import sys


## Implements the 'makefile' command.


# An individual target within a makefile.
class MakefileTarget(object):

  def __init__(self, output, inputs, commands):
    self.output = output
    self.inputs = inputs
    self.commands = commands

  # Returns the string output path for this target.
  def get_output_path(self):
    return self.output

  # Write this target, in Makefile syntax, to the given output stream.
  def write(self, out):
    out.write("%(outpath)s: %(inpaths)s\n\t%(commands)s\n\n" % {
      "outpath": shell_escape(self.output),
      "inpaths": " ".join(map(shell_escape, self.inputs)),
      "commands": "\n\t".join(self.commands)
    })


# The contents of a complete makefile. A makefile object is meant to be dumb and
# basically only concerned with accumulating and then printing the makefile
# source. Any nontrivial logic is the responsibility of whoever is building the
# makefile object.
class Makefile(object):

  def __init__(self):
    self.targets = {}
    self.phonies = set()

  # Add a target that builds the given output from the given inputs by invoking
  # the given commands in sequence.
  def add_target(self, output, inputs, commands, is_phony):
    target = MakefileTarget(output, inputs, commands)
    self.targets[output] = target
    if is_phony:
      self.phonies.add(output)

  # Write this makefile in Makefile syntax to the given stream.
  def write(self, out):
    for name in sorted(self.targets.keys()):
      target = self.targets[name]
      target.write(out)
    # Mike Moffit says: list *all* the phonies.
    if self.phonies:
      out.write(".PHONY: %s\n\n" % " ".join(sorted(list(self.phonies))))


# A segmented name. This is sort of like a relative file path but avoids any
# ambiguities that might be caused by multiple relative paths pointing to the
# same thing and differences in path separators etc. Names compare
# lexicographically and are equal if their parts are structurally equal.
class Name(object):

  def __init__(self, parts):
    self.parts = tuple(parts)

  # Returns a new name that consists of this name followed by the given parts.
  def append(self, *subparts):
    return Name(self.parts + subparts)

  # Returns a new name that consists of the given prefix followed by this name.
  def prepend(self, *prefix):
    return Name(prefix + self.parts)

  # Returns a tuple that holds the parts of this name.
  def get_parts(self):
    return self.parts

  # Returns the last part, for instance the last part of a|b|c is "c".
  def get_last_part(self):
    return self.parts[-1]

  @staticmethod
  def of(*parts):
    return Name(parts)

  def __hash__(self):
    return ~hash(self.parts)

  def __eq__(self, that):
    return (self.parts == that.parts)

  def __cmp__(self, that):
    return cmp(self.parts, that.parts)

  def __str__(self):
    return "::".join(self.parts)

  def __repr__(self):
    return str(self)


# An abstract file wrapper that encapsulates various file operations.
class AbstractFile(object):

  def __init__(self, path, parent):
    self.path = path
    self.parent = parent
    self.children = {}
    self.attribs = {}

  # Creates a new file object of the appropriate type depending on what kind of
  # file the path points to.
  @staticmethod
  def at(path, parent=None):
    if os.path.isdir(path):
      return Folder(path, parent)
    elif os.path.isfile(path):
      return RegularFile(path, parent)
    else:
      return MissingFile(path, parent)

  # Returns the folder that contains this file.
  def get_parent(self):
    if self.parent is None:
      dirname = os.path.dirname(self.path)
      if (not dirname) and os.path.isfile(self.path):
        # If this file is a naked file ("foo.mkmk" say) then we take the parent
        # to be the relative current directory since that's where the file is
        # assumed to be.
        dirname = "."
      self.parent = AbstractFile.at(dirname)
    return self.parent
{'fraction_non_alphanumeric': 0.09624355511907685, 'fraction_numerical': 0.00220967345936656, 'mean_word_length': 3.410936654033568, 'pattern_counts': {'":': 8, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6048167', 'n_tokens_mistral': 2499, 'n_tokens_neox': 2382, 'n_words': 906}