Generate SSD replacement timestamps from typed Jerboa
ober
37ff1a2ecfecd56a4371e24c7428b67f12077375
--- a/templates/ssd-review.ss +++ b/templates/ssd-review.ss @@ -15538,6 +15538,9 @@ (java nio file LinkOption) (java nio file Path) (java security MessageDigest) + (java time Instant) + (java time OffsetDateTime) + (java time format DateTimeFormatter) (javax net ssl HttpsURLConnection) (org json JSONArray) (org json JSONObject)) @@ -15558,16 +15561,23 @@ truthStoreContainedImportPathLocal truthStoreValidateImportedTextLocal truthStoreValidateImportedFileLocal - truthStoreAppendJsonLineLocal) + truthStoreAppendJsonLineLocal + truthStoreTruthTimeLocal + truthStoreShouldReplaceLocal) (type AssetManager) + (type Any) (type Context) + (type DateTimeFormatter) (type Exception) (type File) + (type Instant) (type InputStream) (type Int32) (type LinkOption) (type HttpsURLConnection) (type MessageDigest) + (type Number) + (type OffsetDateTime) (type Path) (type RemoteConfig) (type SsdSession) @@ -15631,12 +15641,6 @@ (destination : File) (text : String)) : Unit (kotlin-member-call atomicWriteText)) - (extern (truthStoreShouldReplaceLocalRaw - (store : TruthStore) - (local : File) - (remoteText : String) - (remoteModified : Int)) : Bool - (kotlin-member-call shouldReplaceLocal)) (extern (truthStoreJsonToPrettyString (json : JSONObject) (indent : Int32)) : String @@ -15644,6 +15648,34 @@ (extern (truthStoreJsonToString (json : JSONObject)) : String (kotlin-member-call toString)) + (extern (truthStoreAnyAsNumber + (value : Any)) : (Nullable Number) + (kotlin-safe-cast Number)) + (extern (truthStoreAnyAsString + (value : Any)) : (Nullable String) + (kotlin-safe-cast String)) + (extern (truthStoreNumberToLong + (value : Number)) : Int + (kotlin-member-call toLong)) + (extern (truthStoreStringToLongOrNull + (value : String)) : (Nullable Int) + (kotlin-member-call toLongOrNull)) + (extern (truthStoreDateTimeFormatterPattern + (pattern : String)) : DateTimeFormatter + (kotlin-call DateTimeFormatter ofPattern)) + (extern (truthStoreOffsetDateTimeParse + (value : String)) : OffsetDateTime + (kotlin-call OffsetDateTime parse)) + (extern (truthStoreOffsetDateTimeParseWithFormatter + (value : String) + (formatter : DateTimeFormatter)) : OffsetDateTime + (kotlin-call OffsetDateTime parse)) + (extern (truthStoreOffsetDateTimeToInstant + (value : OffsetDateTime)) : Instant + (kotlin-member-call toInstant)) + (extern (truthStoreInstantToEpochMilli + (value : Instant)) : Int + (kotlin-member-call toEpochMilli)) (extern (truthStoreConnectionInputStream (connection : HttpsURLConnection)) : InputStream (kotlin-member-get inputStream)) @@ -15678,6 +15710,9 @@ (extern (truthStoreFileInputStream (file : File)) : InputStream (kotlin-member-call inputStream)) + (extern (truthStoreFileLastModified + (file : File)) : Int + (kotlin-member-call lastModified)) (extern (truthStoreInputStreamClose (input : InputStream)) : Unit (kotlin-member-call close)) @@ -16122,8 +16157,7 @@ compareMoreComplete (truthGroupCount truth) (nullableTruthGroupCount local) - (truthStoreShouldReplaceLocalRaw - store + (truthStoreShouldReplaceLocal dest text modified)))) @@ -16237,7 +16271,79 @@ next (truthStoreMaxZipEntryBytes)) "Event log quota exceeded") - (truthStoreAtomicWriteTextRaw store file next))))))) + (truthStoreAtomicWriteTextRaw store file next))))) + (def (truthStoreParseTimestampWithPattern + (value : String)) : (Nullable Int) + (try + (nullable-some + (truthStoreInstantToEpochMilli + (truthStoreOffsetDateTimeToInstant + (truthStoreOffsetDateTimeParseWithFormatter + value + (truthStoreDateTimeFormatterPattern + "yyyy-MM-dd'T'HH:mm:ssZ"))))) + (catch (error : Exception) + (nullable-none Int)))) + (def (truthStoreParseTimestampIso + (value : String)) : (Nullable Int) + (try + (nullable-some + (truthStoreInstantToEpochMilli + (truthStoreOffsetDateTimeToInstant + (truthStoreOffsetDateTimeParse value)))) + (catch (error : Exception) + (nullable-none Int)))) + (def (truthStoreParseTimestampText + (value : String)) : (Nullable Int) + (let ((numeric (truthStoreStringToLongOrNull value))) + (if (not (nullable-null? numeric)) + numeric + (let ((pattern + (truthStoreParseTimestampWithPattern value))) + (if (not (nullable-null? pattern)) + pattern + (truthStoreParseTimestampIso value)))))) + (def (truthStoreJsonValueTimeLocal + (value : (Nullable Any))) : (Nullable Int) + (if (nullable-null? value) + (nullable-none Int) + (let ((raw (nullable-get value))) + (let ((number (truthStoreAnyAsNumber raw))) + (if (not (nullable-null? number)) + (nullable-some + (truthStoreNumberToLong + (nullable-get number))) + (let ((text (truthStoreAnyAsString raw))) + (if (nullable-null? text) + (nullable-none Int) + (truthStoreParseTimestampText + (nullable-get text))))))))) + (def (truthStoreTruthTimeLocal + (truth : JSONObject)) : (Nullable Int) + (truthStoreJsonValueTimeLocal + (truthTimestampValue truth))) + (def (truthStoreJsonTimeLocal + (text : String)) : (Nullable Int) + (try + (truthStoreTruthTimeLocal + (jsonObjectFromText text)) + (catch (error : Exception) + (nullable-none Int)))) + (def (truthStoreShouldReplaceLocal + (local : File) + (remoteText : String) + (remoteModified : Int)) : Bool + (if (localFileMissing local) + #t + (let ((localText + (truthStoreReadLocalText local))) + (if (localTextMatchesRemote localText remoteText) + #f + (shouldReplaceLocalByTimes + (truthStoreJsonTimeLocal localText) + (truthStoreJsonTimeLocal remoteText) + remoteModified + (truthStoreFileLastModified local)))))))) (kotlin-file-lines "com/sfb/ssdreview/TruthStore.kt" ( @@ -16268,8 +16374,6 @@ "import java.security.SecureRandom" "import java.security.cert.CertificateException" "import java.security.cert.X509Certificate" - "import java.time.OffsetDateTime" - "import java.time.format.DateTimeFormatter" "import java.util.zip.ZipEntry" "import java.util.zip.GZIPInputStream" "import java.util.zip.ZipInputStream" @@ -16860,32 +16964,11 @@ " atomicWriteText(file, merged)" " }" "" - " internal fun shouldReplaceLocal(local: File, remoteText: String, remoteModified: Long): Boolean {" - " if (localFileMissing(local)) return true" - " val localText = readLocalText(local)" - " if (localTextMatchesRemote(localText, remoteText)) return false" - " val localGenerated = jsonTime(localText)" - " val remoteGenerated = jsonTime(remoteText)" - " return shouldReplaceLocalByTimes(localGenerated, remoteGenerated, remoteModified, local.lastModified())" - " }" + " internal fun shouldReplaceLocal(local: File, remoteText: String, remoteModified: Long): Boolean =" + " truthStoreShouldReplaceLocal(local, remoteText, remoteModified)" "" " private fun truthTime(truth: JSONObject): Long? =" - " jsonValueTime(truthTimestampValue(truth))" - "" - " private fun jsonTime(text: String): Long? = try {" - " val json = jsonObjectFromText(text)" - " truthTime(json)" - " } catch (_: Exception) {" - " null" - " }" - "" - " private fun jsonValueTime(value: Any?): Long? = when (value) {" - " is Number -> value.toLong()" - " is String -> value.toLongOrNull()" - " ?: runCatching { OffsetDateTime.parse(value, DateTimeFormatter.ofPattern(\"yyyy-MM-dd'T'HH:mm:ssZ\")).toInstant().toEpochMilli() }.getOrNull()" - " ?: runCatching { OffsetDateTime.parse(value).toInstant().toEpochMilli() }.getOrNull()" - " else -> null" - " }" + " truthStoreTruthTimeLocal(truth)" "" " internal fun appendJsonLine(file: File, json: JSONObject) =" " truthStoreAppendJsonLineLocal(this, file, json)"