Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Build: Allow import directories. #187

Open
wants to merge 3 commits into from

1 participant

@jorix

After 8047afd can be used a directory name in [exclude] section in a configuration file.

This Pull Request proposes to extend the use of directory names to all other sections.

Implementation:

Has been developed the method importFiles to import files from any section. This method imports the files if they have not previously been imported and are not excluded. If a directory name found walking through the directory and imports its files (when the [include] section is empty is equivalent to ./)

The new code uses the cfg object on many points, so to avoid checks as if cfg:, always creates a cfg object still not reporting configuration file.

Care has been taken to the execution log is clearer separating the phases using a blank line.

Some changes in behavior:

  • If a file is reported in the [last] section not it's necessary to ensure that previously reported on [first] or [include]
  • Allows importing files outside the library, eg using ../my_directory/my_source.js
  • It is not possible to repeat a file (now is possible if reported in [first] and [last] simultaneously)
@jorix

Please review.

@elemoine "Pull" was already to 2.12, and now I see that has no milestone.

NOTE: This ticket Involves a large change in "mergejs.py", so I thought it would not be accepted. I was surprised when I saw it for 2.12.


Sorry, now I know why, I read your note in dev (I do not read dev from the mail)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 28, 2012
  1. @jorix

    Build: Allow import directories.

    jorix authored
  2. @jorix
Commits on May 12, 2012
  1. @jorix
This page is out of date. Refresh to see the latest.
Showing with 79 additions and 45 deletions.
  1. +79 −45 tools/mergejs.py
View
124 tools/mergejs.py
@@ -121,10 +121,22 @@ class Config:
"""
- def __init__(self, filename):
+ def __init__(self, filename, sourceDirectory):
"""
Parses the content of the named file and stores the values.
"""
+ self.sourceDirectory = sourceDirectory
+ self.configFile = filename
+ if not filename:
+ self.configFile = "(none)"
+ self.forceFirst = []
+ self.forceLast = []
+ self.include = []
+ self.exclude = []
+
+ if not os.path.isfile(filename):
+ raise MissingImport("Config file '%s' not found." % filename)
+
lines = [re.sub("#.*?$", "", line).strip() # Assumes end-of-line character is present
for line in open(filename)
if line.strip() and not line.strip().startswith("#")] # Skip blank lines and comments
@@ -155,23 +167,7 @@ def getNames (sourceDirectory, configFile = None):
def run (sourceDirectory, outputFilename = None, configFile = None,
returnAsListOfNames = False):
- cfg = None
- if configFile:
- cfg = Config(configFile)
-
- allFiles = []
-
- ## Find all the Javascript source files
- for root, dirs, files in os.walk(sourceDirectory):
- for filename in files:
- if filename.endswith(SUFFIX_JAVASCRIPT) and not filename.startswith("."):
- filepath = os.path.join(root, filename)[len(sourceDirectory)+1:]
- filepath = filepath.replace("\\", "/")
- if cfg and cfg.include:
- if filepath in cfg.include or filepath in cfg.forceFirst:
- allFiles.append(filepath)
- elif (not cfg) or (not undesired(filepath, cfg.exclude)):
- allFiles.append(filepath)
+ cfg = Config(configFile, sourceDirectory)
## Header inserted at the start of each file in the output
HEADER = "/* " + "=" * 70 + "\n %s\n" + " " + "=" * 70 + " */\n\n"
@@ -179,54 +175,44 @@ def run (sourceDirectory, outputFilename = None, configFile = None,
files = {}
## Import file source code
- ## TODO: Do import when we walk the directories above?
- for filepath in allFiles:
- print "Importing: %s" % filepath
- fullpath = os.path.join(sourceDirectory, filepath).strip()
- content = open(fullpath, "U").read() # TODO: Ensure end of line @ EOF?
- files[filepath] = SourceFile(filepath, content, cfg.exclude) # TODO: Chop path?
-
- print
-
- from toposort import toposort
+ cfg.forceFirst = importFiles("[first]", cfg.forceFirst, False, cfg, files)
+ cfg.forceLast = importFiles("[last]", cfg.forceLast, False, cfg, files)
+ if len(cfg.include) == 0:
+ importFiles("[include]", ["."], True, cfg, files)
+ else:
+ importFiles("[include]", cfg.include, True, cfg, files)
+ print "\nImport required files:"
complete = False
resolution_pass = 1
-
while not complete:
complete = True
-
## Resolve the dependencies
print "Resolution pass %s... " % resolution_pass
resolution_pass += 1
-
for filepath, info in files.items():
for path in info.requires:
if not files.has_key(path):
complete = False
- fullpath = os.path.join(sourceDirectory, path).strip()
- if os.path.exists(fullpath):
- print "Importing: %s" % path
- content = open(fullpath, "U").read() # TODO: Ensure end of line @ EOF?
- files[path] = SourceFile(path, content, cfg.exclude) # TODO: Chop path?
- else:
+ try:
+ importFile("", path, True, cfg, files)
+ except MissingImport:
raise MissingImport("File '%s' not found (required by '%s')." % (path, filepath))
# create dictionary of dependencies
+ print "\nSorting..."
dependencies = {}
for filepath, info in files.items():
dependencies[filepath] = info.requires
-
- print "Sorting..."
+ from toposort import toposort
order = toposort(dependencies) #[x for x in toposort(dependencies)]
## Move forced first and last files to the required position
- if cfg:
- print "Re-ordering files..."
- order = cfg.forceFirst + [item
- for item in order
- if ((item not in cfg.forceFirst) and
- (item not in cfg.forceLast))] + cfg.forceLast
+ print "\nRe-ordering files..."
+ order = cfg.forceFirst + [item
+ for item in order
+ if ((item not in cfg.forceFirst) and
+ (item not in cfg.forceLast))] + cfg.forceLast
print
## Output the files in the determined order
@@ -263,6 +249,54 @@ def run (sourceDirectory, outputFilename = None, configFile = None,
open(outputFilename, "w").write("".join(result))
return "".join(result)
+def importFiles(sectionName, inputFiles, excludeFiles, cfg, files):
+ print "\nImport \"%s\" files:" % sectionName
+ outputFiles = []
+ for filepath in inputFiles:
+ if filepath.endswith(SUFFIX_JAVASCRIPT):
+ outputFiles += importFile(sectionName, filepath, excludeFiles, cfg, files)
+ else:
+ outputFiles += importDirectory(sectionName, filepath, excludeFiles, cfg, files)
+ return outputFiles
+
+def importDirectory(sectionName, directoryName, excludeFiles, cfg, files):
+ # Normalize directory name
+ directoryName = directoryName.replace("\\", "/")
+ if directoryName.startswith("./"):
+ directoryName = directoryName[2:]
+ elif directoryName == ".":
+ directoryName = ""
+
+ fullpath = os.path.join(cfg.sourceDirectory, directoryName).strip().replace("\\", "/")
+ if not os.path.isdir(fullpath):
+ raise MissingImport("Directory '%s' not found. Check %s in config file '%s'" %
+ (fullpath, sectionName, cfg.configFile))
+
+ print "Import from directory \"%s\":" % fullpath
+ outputFiles = []
+ for root, dirs, directoryFiles in os.walk(fullpath):
+ for filename in directoryFiles:
+ if filename.endswith(SUFFIX_JAVASCRIPT) and not filename.startswith("."):
+ filepath = os.path.join(root, filename)[len(cfg.sourceDirectory)+1:]
+ outputFiles += importFile(sectionName, filepath, excludeFiles, cfg, files)
+ print "End of directory"
+ return outputFiles
+
+def importFile(sectionName, filepath, excludeFiles, cfg, files):
+ # Normalize file name
+ filepath = filepath.replace("\\", "/")
+ if excludeFiles and (filepath in files or undesired(filepath, cfg.exclude)):
+ return []
+ else:
+ fullpath = os.path.join(cfg.sourceDirectory, filepath).strip().replace("\\","/")
+ if not os.path.isfile(fullpath):
+ raise MissingImport("File '%s' not found. Check %s in config file '%s'" %
+ (fullpath, sectionName, cfg.configFile))
+ print "Importing: %s" % filepath
+ content = open(fullpath, "U").read() # TODO: Ensure end of line @ EOF?
+ files[filepath] = SourceFile(filepath, content, cfg.exclude)
+ return [filepath]
+
if __name__ == "__main__":
import getopt
Something went wrong with that request. Please try again.