536 export_files: List[(Path, Int, List[String])], |
536 export_files: List[(Path, Int, List[String])], |
537 meta_digest: SHA1.Digest) |
537 meta_digest: SHA1.Digest) |
538 { |
538 { |
539 def deps: List[String] = parent.toList ::: imports |
539 def deps: List[String] = parent.toList ::: imports |
540 |
540 |
541 def dirs: List[Path] = dir :: directories.map(_._1) |
541 def dirs: List[(Path, Boolean)] = (dir, false) :: directories |
542 def dirs_strict: List[Path] = dir :: (for { (d, false) <- directories } yield d) |
|
543 |
542 |
544 def timeout: Time = Time.seconds(options.real("timeout") * options.real("timeout_scale")) |
543 def timeout: Time = Time.seconds(options.real("timeout") * options.real("timeout_scale")) |
545 |
544 |
546 def bibtex_entries: List[Text.Info[String]] = |
545 def bibtex_entries: List[Text.Info[String]] = |
547 (for { |
546 (for { |
559 |
558 |
560 if (exclude_session(name)) error("Bad session name") |
559 if (exclude_session(name)) error("Bad session name") |
561 if (is_pure(name) && entry.parent.isDefined) error("Illegal parent session") |
560 if (is_pure(name) && entry.parent.isDefined) error("Illegal parent session") |
562 if (!is_pure(name) && !entry.parent.isDefined) error("Missing parent session") |
561 if (!is_pure(name) && !entry.parent.isDefined) error("Missing parent session") |
563 |
562 |
|
563 val session_path = dir + Path.explode(entry.path) |
564 val directories = |
564 val directories = |
565 for { (d, b) <- entry.directories } |
565 for { (dir, overlapping) <- entry.directories } |
566 yield (dir + Path.explode(d), b) |
566 yield (session_path + Path.explode(dir), overlapping) |
567 |
567 |
568 val session_options = options ++ entry.options |
568 val session_options = options ++ entry.options |
569 |
569 |
570 val theories = |
570 val theories = |
571 entry.theories.map({ case (opts, thys) => |
571 entry.theories.map({ case (opts, thys) => |
597 |
597 |
598 val meta_digest = |
598 val meta_digest = |
599 SHA1.digest((name, chapter, entry.parent, entry.directories, entry.options, entry.imports, |
599 SHA1.digest((name, chapter, entry.parent, entry.directories, entry.options, entry.imports, |
600 entry.theories_no_position, conditions, entry.document_files).toString) |
600 entry.theories_no_position, conditions, entry.document_files).toString) |
601 |
601 |
602 Info(name, chapter, dir_selected, entry.pos, entry.groups, dir + Path.explode(entry.path), |
602 Info(name, chapter, dir_selected, entry.pos, entry.groups, session_path, |
603 entry.parent, entry.description, directories, session_options, |
603 entry.parent, entry.description, directories, session_options, |
604 entry.imports, theories, global_theories, document_files, export_files, meta_digest) |
604 entry.imports, theories, global_theories, document_files, export_files, meta_digest) |
605 } |
605 } |
606 catch { |
606 catch { |
607 case ERROR(msg) => |
607 case ERROR(msg) => |
669 else graph.new_node(info.name, info) |
669 else graph.new_node(info.name, info) |
670 } |
670 } |
671 val build_graph = add_edges(info_graph, "parent", _.parent) |
671 val build_graph = add_edges(info_graph, "parent", _.parent) |
672 val imports_graph = add_edges(build_graph, "imports", _.imports) |
672 val imports_graph = add_edges(build_graph, "imports", _.imports) |
673 |
673 |
674 val strict_directories: Map[JFile, String] = |
674 val session_directories: Map[JFile, (String, Boolean)] = |
675 (Map.empty[JFile, String] /: |
675 (Map.empty[JFile, (String, Boolean)] /: |
676 (for { |
676 (for { |
677 session <- imports_graph.topological_order.iterator |
677 session <- imports_graph.topological_order.iterator |
678 info = info_graph.get_node(session) |
678 info = info_graph.get_node(session) |
679 dir <- info.dirs_strict.iterator |
679 dir_overlapping <- info.dirs.iterator |
680 } yield (info, dir)))({ case (dirs, (info, dir)) => |
680 } yield (info, dir_overlapping)))({ case (dirs, (info, (dir, overlapping))) => |
681 val session = info.name |
681 val session = info.name |
682 val canonical_dir = dir.canonical_file |
682 val canonical_dir = dir.canonical_file |
|
683 def update(over: Boolean) = dirs + (canonical_dir -> (session -> over)) |
683 dirs.get(canonical_dir) match { |
684 dirs.get(canonical_dir) match { |
684 case Some(session1) if session != session1 => |
685 case Some((session1, overlapping1)) => |
685 val info1 = info_graph.get_node(session1) |
686 if (session == session1) update(overlapping || overlapping1) |
686 error("Duplicate use of directory " + dir + |
687 else if (overlapping && !overlapping1) dirs |
687 "\n for session " + quote(session1) + Position.here(info1.pos) + |
688 else if (!overlapping && overlapping1) update(overlapping) |
688 "\n vs. session " + quote(session) + Position.here(info.pos)) |
689 else { |
689 case _ => dirs + (canonical_dir -> session) |
690 val info1 = info_graph.get_node(session1) |
|
691 error("Duplicate use of directory " + dir + |
|
692 "\n for session " + quote(session1) + Position.here(info1.pos) + |
|
693 "\n vs. session " + quote(session) + Position.here(info.pos)) |
|
694 } |
|
695 case None => update(overlapping) |
690 } |
696 } |
691 }) |
697 }) |
692 |
698 |
693 val global_theories: Map[String, String] = |
699 val global_theories: Map[String, String] = |
694 (Thy_Header.bootstrap_global_theories.toMap /: |
700 (Thy_Header.bootstrap_global_theories.toMap /: |
703 error("Duplicate global theory " + quote(thy) + Position.here(info.pos)) |
709 error("Duplicate global theory " + quote(thy) + Position.here(info.pos)) |
704 case _ => global + (thy -> qualifier) |
710 case _ => global + (thy -> qualifier) |
705 } |
711 } |
706 }) |
712 }) |
707 |
713 |
708 new Structure(strict_directories, global_theories, build_graph, imports_graph) |
714 new Structure(session_directories, global_theories, build_graph, imports_graph) |
709 } |
715 } |
710 |
716 |
711 final class Structure private[Sessions]( |
717 final class Structure private[Sessions]( |
712 val strict_directories: Map[JFile, String], |
718 val session_directories: Map[JFile, (String, Boolean)], |
713 val global_theories: Map[String, String], |
719 val global_theories: Map[String, String], |
714 val build_graph: Graph[String, Info], |
720 val build_graph: Graph[String, Info], |
715 val imports_graph: Graph[String, Info]) |
721 val imports_graph: Graph[String, Info]) |
716 { |
722 { |
717 sessions_structure => |
723 sessions_structure => |
779 val sessions = graph.all_preds(selected(graph, sel)).filterNot(excluded) |
785 val sessions = graph.all_preds(selected(graph, sel)).filterNot(excluded) |
780 graph.restrict(graph.all_preds(sessions).toSet) |
786 graph.restrict(graph.all_preds(sessions).toSet) |
781 } |
787 } |
782 |
788 |
783 new Structure( |
789 new Structure( |
784 strict_directories, global_theories, restrict(build_graph), restrict(imports_graph)) |
790 session_directories, global_theories, restrict(build_graph), restrict(imports_graph)) |
785 } |
791 } |
786 |
792 |
787 def selection_deps( |
793 def selection_deps( |
788 options: Options, |
794 options: Options, |
789 selection: Selection, |
795 selection: Selection, |