private ProjectWrapper(
      final GantBinding binding,
      final String prjDir,
      final String setupScript,
      final Map<String, String> pathVariables,
      final boolean loadHistory) {
    affectedFiles = new HashSet<String>();

    myProject = new GantBasedProject(binding == null ? new GantBinding() : binding);
    myProjectBuilder = myProject.getBuilder();

    final File prjFile = new File(prjDir);
    final boolean dirBased = !(prjFile.isFile() && prjDir.endsWith(".ipr"));

    myRoot = dirBased ? getCanonicalPath(prjDir) : getCanonicalPath(prjFile.getParent());

    final String loadPath = dirBased ? getAbsolutePath(myIDEADir) : prjDir;

    IdeaProjectLoader.loadFromPath(
        myProject,
        loadPath,
        pathVariables != null ? pathVariables : Collections.<String, String>emptyMap(),
        setupScript);

    myProjectSnapshot =
        myHomeDir
            + File.separator
            + myJPSDir
            + File.separator
            + myRoot.replace(File.separatorChar, myFileSeparatorReplacement);

    try {
      dependencyMapping = new Mappings(getMapDir());
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    backendCallback = dependencyMapping.getCallback();

    for (Module m : myProject.getModules().values()) {
      myModules.put(m.getName(), new ModuleWrapper(m));
    }

    for (Library l : myProject.getLibraries().values()) {
      myLibraries.put(l.getName(), new LibraryWrapper(l));
    }

    myHistory = loadHistory ? loadSnapshot(affectedFiles) : null;

    if (loadHistory) {
      dependencyMapping = myHistory.dependencyMapping;
    }
  }
  public void makeModule(final String modName, final Flags flags) {
    if (modName == null) {
      makeModules(myProject.getModules().values(), flags);
    } else {
      final Module module = myProject.getModules().get(modName);
      final List<Module> list = new ArrayList<Module>();

      if (module == null) {
        System.err.println("Module \"" + modName + "\" not found in project \"" + myRoot + "\"");
        return;
      }

      list.add(module);

      makeModules(list, flags);
    }
  }
 public void rebuild() {
   try {
     dependencyMapping.clean();
     makeModules(myProject.getModules().values(), defaultFlags);
   } catch (IOException e) {
     throw new RuntimeException(e);
   }
 }
  public void makeModules(final Collection<Module> initial, final Flags flags) {
    if (myHistory == null && !flags.tests()) {
      clean();
    }

    new Logger(flags) {
      @Override
      public void log(final PrintStream stream) {
        stream.println("Request to make modules:");
        logMany(stream, initial);
        stream.println("End of request");
      }
    }.log();

    final ClasspathKind kind = ClasspathKind.compile(flags.tests());

    final Set<Module> modules = new HashSet<Module>();
    final Set<String> marked = new HashSet<String>();
    final Map<String, Boolean> visited = new HashMap<String, Boolean>();
    final Set<String> frontier = new HashSet<String>();

    final Map<String, Set<String>> reversedDependencies = new HashMap<String, Set<String>>();
    final DotPrinter printer = new DotPrinter(flags.logStream());

    printer.header();

    for (Module m : myProject.getModules().values()) {
      final String mName = m.getName();

      printer.node(mName);

      for (ClasspathItem cpi : m.getClasspath(kind)) {
        if (cpi instanceof Module) {
          final String name = ((Module) cpi).getName();

          printer.edge(name, mName);

          Set<String> sm = reversedDependencies.get(name);

          if (sm == null) {
            sm = new HashSet<String>();
            reversedDependencies.put(name, sm);
          }

          sm.add(mName);
        }
      }
    }

    printer.footer();

    // Building "upper" subgraph

    printer.header();

    new Object() {
      public void run(final Collection<Module> initial) {
        if (initial == null) return;

        for (Module module : initial) {

          final String mName = module.getName();

          if (marked.contains(mName)) continue;

          printer.node(mName);

          final List<Module> dep = new ArrayList<Module>();

          for (ClasspathItem cpi : module.getClasspath(kind)) {
            if (cpi instanceof Module && !marked.contains(((Module) cpi).getName())) {
              printer.edge(((Module) cpi).getName(), mName);
              dep.add((Module) cpi);
            }
          }

          if (dep.size() == 0) {
            frontier.add(mName);
          }

          marked.add(mName);

          run(dep);
        }
      }
    }.run(initial);

    printer.footer();

    // Traversing "upper" subgraph and collecting outdated modules and their descendants
    new Object() {
      public void run(final Collection<String> initial, final boolean force) {
        if (initial == null) return;

        for (String moduleName : initial) {
          if (!marked.contains(moduleName)) continue;

          final Boolean property = visited.get(moduleName);

          if (property == null || !property && force) {
            final boolean outdated = getModule(moduleName).isOutdated(flags.tests(), myHistory);

            if (force || outdated) {
              visited.put(moduleName, true);
              modules.add(myProject.getModules().get(moduleName));

              run(reversedDependencies.get(moduleName), true);
            } else {
              if (property == null) {
                visited.put(moduleName, false);
              }
              run(reversedDependencies.get(moduleName), false);
            }
          }
        }
      }
    }.run(frontier, flags.force());

    new Logger(flags) {
      @Override
      public void log(PrintStream stream) {
        stream.println("Propagated modules:");
        logMany(stream, modules);
        stream.println("End of propagated");
      }
    }.log();

    if (modules.size() == 0 && !flags.force()) {
      System.out.println("All requested modules are up-to-date.");
      return;
    }

    final BusyBeaver beaver = new BusyBeaver(myProjectBuilder);

    myProjectBuilder.buildStart();

    if (flags.tests()) {
      beaver.build(
          modules,
          new Flags() {
            public boolean tests() {
              return false;
            }

            public boolean incremental() {
              return flags.incremental();
            }

            public boolean force() {
              return flags.force();
            }

            public PrintStream logStream() {
              return flags.logStream();
            }
          });
    }

    beaver.build(modules, flags);

    myProjectBuilder.buildStop();

    for (Module mod : modules) {
      getModule(mod.getName()).updateOutputStatus();
    }
  }