Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserve bundle creation date when creating and applying delta updates #2583

Merged
merged 2 commits into from
Sep 30, 2024

Conversation

zorgiepoo
Copy link
Member

@zorgiepoo zorgiepoo commented Jun 15, 2024

This will preserve the file creation date of the new app bundle, but not the file creation date of any of the files inside the new app bundle because tracking those changes is complex/undesirable. Other updater systems that use delta updates (like the App Store) also don't make guarantees about preserving that metadata for files inside the app bundle when applying delta updates.

This bumps the major binary delta version to 4 and will need documentation updates. generate_appcast has been updated to handle the major version. A new test has been added for testing that the new bundle creation date is also preserved.

Misc Checklist

  • My change requires a documentation update on Sparkle's website repository
  • My change requires changes to generate_appcast, generate_keys, or sign_update

Testing

I tested and verified my change by using one or multiple of these methods:

  • Sparkle Test App
  • Unit Tests
  • My own app
  • Other (please specify)

I will run through:

  • Test running Sparkle Test App with DELTA mode for creating/applying version 4 delta patch
  • Test preservation of bundle creation date in unit tests
  • Test applying old version 3 delta patch
  • Test creating version 3 delta patch and then applying it
  • Test creating version 4 delta patch and then applying it
  • Test creating version 4 delta patch and failing to apply it from older BinaryDelta version
  • Test creating updates with generate_appcast and ensure it creates version 3 patches for old updates, and version 4 patches for new updates

macOS version tested: 14.5 (23F79)

This will preserve the file creation date of the new app bundle, but not the file creation date of any of the files inside the new app bundle because tracking those changes is complex/undesirable. Other updater systems that use delta updates (like the App Store) also don't make guarantees about preserving that metadata for files inside the app bundle when applying delta updates.

This bumps the major binary delta version to 4 and will need documentation updates. generate_appcast has been updated to handle the major version. A new test has been added for testing that the new bundle creation date is also preserved.
@zorgiepoo zorgiepoo added this to the 2.7 milestone Jun 15, 2024
@zorgiepoo
Copy link
Member Author

cc @core-code for awareness

@zorgiepoo zorgiepoo changed the title Preserve bundle creation date when applying delta updates Preserve bundle creation date when creating and applying delta updates Jun 15, 2024
@core-code
Copy link
Contributor

awesome, many thanks! i've been meaning to send a patch about this issue for some time, but time is always in short supply.

a few questions and/or requests:
• i see this preserves the creation date of the bundle, but what about the modification date? for example ls only displays the modification date
• would it be possible to also preserve the dates for a few items inside the bundle? the rationale here is that the bundle is often touched by many tools, so its date may be quite unreliable anyway. for this reason MacUpdater has never looked directly at the app bundle when trying to determine the release date of an app, but instead looked for the dates of /Contents/Info.plist and /Contents/MacOS/$(CFBundleExecutable)

@zorgiepoo
Copy link
Member Author

zorgiepoo commented Jun 15, 2024

Sparkle always updates the modification date of the bundle before installing it to the current time, even absent of delta updates support. Historically this is due as a way to update the bundle for LaunchServices (I'm aware of LSRegisterURL but I don't think I want to change this and don't want to use LS-related functionality from the daemon. In the long ago past using LSRegisterURL was tried-and-quickly-reverted but I would have to dig that up again to see why). If I look at apps on my machine installed by the App Store, I see the modification dates are ahead of the creation dates, so I believe the App Store does the same thing as Sparkle (i.e, update modification time to current time when installing an app update).

For preserving these dates for "new" files inside the app bundle, that will be considerably more complicated (there are a number of permutations for the delta-update commands) and require more space in the archive. I don't think I want to do that and don't consider them important enough to preserve.

The primary motivation behind this change for me is to provide useful dates when users view info on the app bundle in Finder. The modification date reflects when the app was last updated by Sparkle/App Store, and the creation date reflects when the developer originally created the app.

From a point of view I actually think the creation date of the app bundle is more accurate than the creation date of files inside of it. For example for an app installed from the App Store, the creation date of the app bundle reflects the original developer creating the app, while the creation date of Contents/MacOS/$(CFBundleExecutable) may instead reflect when the app was re-signed by the App Store -- an "internal" detail so to speak. Similarly, what Sparkle may write inside an app bundle to update it in the case of delta updates is an "internal" detail. edit: some other external tool could update the executable with a new creation date too, for example, to strip out an architecture slice.

I may experiment with making more changes later.
@core-code
Copy link
Contributor

sorry for the delay here (my pleas for the 30 hour day still go unheard…).

The primary motivation behind this change for me is to provide useful dates when users view info on the app bundle in Finder. The modification date reflects when the app was last updated by Sparkle/App Store, and the creation date reflects when the developer originally created the app.

this sounds useful and it would be great if that were always the case

From a point of view I actually think the creation date of the app bundle is more accurate than the creation date of files inside of it.

unfortunately it is just not true. i like to talk with hard data, so i've downloaded a lot of apps to run some tests. 1045 of those apps were code-signed which provides the best possible estimate for the "true release date" of the app.

i looked at the creation and modification dates of the bundle, the info plist and the executable, and calculated their difference to the true release date. for the sake of the experiment i ignored deviations of less than 5 days.

the results are
Bundle Creation Date: 50 deviations
Bundle Modification Date: 62 deviations

Plist Creation Date: 16 deviations
Plist Modification Date: 12 deviations

Exe Creation Date: 3 deviations
Exe Modification Date: 2 deviations

so the results are clear, looking at the bundle is a bad way to find out when an app has been released/built. the plist is a lot better and the exe is definitely the best approximation.

also, the bundle dates are often off by a LOT. brand new Ableton releases have bundle creation dates from 2011, and in a few cases the bundle is older than 2010 and in some cases we even see dates from the past millennium.

these results are from freshly-downloaded apps. i believe the results will be even more pronounced in the real world. while there are ways the exe or plist can get touched, it is a lot more likely for the bundle dates to become unreliable because they have been modified.

so, i had hoped we could simplify the "app release date detection" to just looking at the bundle creation date, but given the above results that would be a severe regression.

For preserving these dates for "new" files inside the app bundle, that will be considerably more complicated and require more space in the archive.

i am not sure why this would require much more space. 2 dates (plist and exe) should be encodable in 4 bytes when just storing the date and dismissing the time.

regarding complications, is this something i should look into?

@zorgiepoo
Copy link
Member Author

zorgiepoo commented Jul 4, 2024

At least with App Store apps, the creation date of the bundle is reflective of the developer creating the app while the creation date of the main executable (which is later) is reflective of when the executable is re-signed by the App Store. This is a deviation but doesn't mean the outer bundle one is "more wrong", at least for this case.

For my end it's just simpler to only account for the bundle, which is the most user-facing date. The format does not hardcode specifics for Info.plist files or main executable files, and if it were to remain that way, it may need to record a date per new changed file (and of course similar to App Store deltas it would not record dates for other files that haven't changed in content). My direct goal is not to adhere to a system that makes it easier for other tools to find a "release date" across various different ways developers distribute apps.

(I just haven't merged this because it's been on my backlog, and also I'm hoping to make other unrelated major changes to the format.. maybe)

@core-code
Copy link
Contributor

For my end it's just simpler to only account for the bundle, which is the most user-facing date.
My direct goal is not to adhere to a system that makes it easier for other tools to find a "release date" across various different ways developers distribute apps.

fully agreed and thanks anyway. a note to the documentation ( https://sparkle-project.org/documentation/delta-updates/ ) should suffice. something about that applying updates using delta updates has a bit-for-bit identical result for all data, but metadata (like creation dates) will not be preserved.

FWIW, code-signature dates as release dates are more reliable anyway and luckily there aren't so many unsigned apps anyway.

@zorgiepoo zorgiepoo merged commit 6848a88 into 2.x Sep 30, 2024
2 checks passed
@zorgiepoo zorgiepoo deleted the creation-date-preservation-deltas branch September 30, 2024 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants