Source: ocaml Version: 4.01.0-5 Severity: wishlist Tags: patch User: reproducible-builds@lists.alioth.debian.org Usertags: timestamps X-Debbugs-Cc: reproducible-builds@lists.alioth.debian.org Hi! While working on the “reproducible builds” effort [1], we have noticed that packages using ocamldoc to write manpages could not be built reproducibly, including ocaml itself. The attached patch removes extra timestamps from the generated documentation. Once applied, ocamldoc-generated manpages can be built reproducibly in our current experimental framework. Note: this patch itself does not make ocaml build reproducibly, I will submit a patch for that after #794583 is fixed. [1]: https://wiki.debian.org/ReproducibleBuilds Regards, Valentin
diff -u../chroot/root/ocaml-4.01.0/ocamldoc/odoc_man.ml
--- ocamldoc/odoc_man.ml 2012-10-15 19:50:56.000000000 +0200
+++ ../chroot/root/ocaml-4.01.0/ocamldoc/odoc_man.ml 2015-08-03 23:33:12.000000000 +0200
@@ -720,14 +720,13 @@
(** Generate the man page for the given class.*)
method generate_for_class cl =
Odoc_info.reset_type_names () ;
- let date = Unix.time () in
let file = self#file_name cl.cl_name in
try
let chanout = self#open_out file in
let b = new_buf () in
bs b (".TH \""^cl.cl_name^"\" ");
bs b !man_section ;
- bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b (" source: "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
@@ -779,14 +778,13 @@
(** Generate the man page for the given class type.*)
method generate_for_class_type ct =
Odoc_info.reset_type_names () ;
- let date = Unix.time () in
let file = self#file_name ct.clt_name in
try
let chanout = self#open_out file in
let b = new_buf () in
bs b (".TH \""^ct.clt_name^"\" ");
bs b !man_section ;
- bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b (" source: "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
@@ -836,14 +834,13 @@
(** Generate the man file for the given module type.
@raise Failure if an error occurs.*)
method generate_for_module_type mt =
- let date = Unix.time () in
let file = self#file_name mt.mt_name in
try
let chanout = self#open_out file in
let b = new_buf () in
bs b (".TH \""^mt.mt_name^"\" ");
bs b !man_section ;
- bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b (" source: "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
@@ -914,14 +911,13 @@
(** Generate the man file for the given module.
@raise Failure if an error occurs.*)
method generate_for_module m =
- let date = Unix.time () in
let file = self#file_name m.m_name in
try
let chanout = self#open_out file in
let b = new_buf () in
bs b (".TH \""^m.m_name^"\" ");
bs b !man_section ;
- bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b (" source: "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
@@ -1045,14 +1041,13 @@
| Res_const (_,f) -> f.vc_name
)
in
- let date = Unix.time () in
let file = self#file_name name in
try
let chanout = self#open_out file in
let b = new_buf () in
bs b (".TH \""^name^"\" ");
bs b !man_section ;
- bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" ");
+ bs b (" source: "^Odoc_misc.current_date^" ");
bs b "OCamldoc ";
bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n");
bs b ".SH NAME\n";
diff -u ocamldoc/odoc_misc.ml ../chroot/root/ocaml-4.01.0/ocamldoc/odoc_misc.ml
--- ocamldoc/odoc_misc.ml 2012-10-15 19:50:56.000000000 +0200
+++ ../chroot/root/ocaml-4.01.0/ocamldoc/odoc_misc.ml 2015-08-03 23:26:58.000000000 +0200
@@ -223,9 +223,9 @@
None -> None
| Some v -> Some (f v)
-let string_of_date ?(hour=true) d =
+let string_of_date ?(absolute=false) ?(hour=true) d =
let add_0 s = if String.length s < 2 then "0"^s else s in
- let t = Unix.localtime d in
+ let t = (if absolute then Unix.gmtime else Unix.localtime) d in
(string_of_int (t.Unix.tm_year + 1900))^"-"^
(add_0 (string_of_int (t.Unix.tm_mon + 1)))^"-"^
(add_0 (string_of_int t.Unix.tm_mday))^
@@ -238,6 +238,14 @@
""
)
+let current_date =
+ let time =
+ try
+ float_of_string (Sys.getenv "SOURCE_DATE_EPOCH")
+ with
+ Sys_error _ -> Unix.time ()
+ in string_of_date ~absolute: true ~hour: false time
+
let rec text_list_concat sep l =
match l with
diff -u ocamldoc/odoc_misc.mli ../chroot/root/ocaml-4.01.0/ocamldoc/odoc_misc.mli
--- ocamldoc/odoc_misc.mli 2012-10-15 19:50:56.000000000 +0200
+++ ../chroot/root/ocaml-4.01.0/ocamldoc/odoc_misc.mli 2015-08-03 23:30:13.000000000 +0200
@@ -62,7 +62,12 @@
(** Return a string representing a date given as a number of seconds
since 1970. The hour is optionnaly displayed. *)
-val string_of_date : ?hour:bool -> float -> string
+val string_of_date : ?absolute:bool -> ?hour:bool -> float -> string
+
+(* Value returned by string_of_date for current time.
+ * Uses environment variable SOURCE_DATE_EPOCH if set; falls back to
+ * current timestamp otherwise. *)
+val current_date : string
(** Return the first sentence (until the first dot) of a text.
Don't stop in the middle of [Code], [Verbatim], [List], [Lnum],
Attachment:
signature.asc
Description: OpenPGP digital signature