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

Add fetch-interval to outdated command to skip fetching the dependencies #2714

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

mollyIV
Copy link
Contributor

@mollyIV mollyIV commented Feb 24, 2019

Motivation and Context

carthage outdated --xcode-warnings (Xcode build phase) command fetches the dependencies each time when executed. In order to improve the performance of the command, we'd like to introduce a new parameter fetch-interval. This parameter specifies how often the dependencies should be fetched from the remote location. Example usage:

carthage outdated --xcode-warning --fetch-interval 30

fetch-interval - the minimum amount of time that must elapse between dependencies fetch operation (provided in minutes seconds)

#2698

Description

This PR is draft one [WIP]. Kindly ask you to check the review comments 🙏
EDIT: PR is ready for review 🙏

It's my first Carthage contribution 🎉

if shouldIgnoreFetching {
// TODO: Non-fetching changes required.
carthage.println("The dependencies will not be fetched due to non-expired fetch interval.")
return project.outdatedDependencies(options.isVerbose)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that we do download the remote dependencies when we initialise ResolverProtocol type object:

let resolver = resolver ?? resolverType.init(
versionsForDependency: versions(for:),
dependenciesForDependency: dependencies,
resolvedGitReference: resolvedGitReference
)

Wondering if modifying the resolver initialisation is a way to go, i.e. passing [:] to resolver's versions 🤔

Could you guys please give me a hint what would be the best way to ignore fetching the remote dependencies? 🙏

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just set FetchCache.fetchCacheInterval to the value that's passed in. That should be all you need to do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👋 @mdiep Thanks for the comment and your help 🙇 Just to double check: FetchCache.fetchCacheInterval is just a static property without the persistent storage behind it, so we need the UserDefaults logic I introduced in this PR anyway, right?

With the suggested changes we are going to have:

...
if shouldIgnoreFetching {
    carthage.println("The dependencies will not be fetched due to non-expired fetch interval.")
    FetchCache.fetchCacheInterval = TimeInterval(options.fetchInterval)
    return project.outdatedDependencies(options.isVerbose)
} 
....

Could you please just confirm we are on the same page? 🙏

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so we need the UserDefaults logic I introduced in this PR anyway, right?

Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please correct me if I am wrong @mdiep , but I though carthage (CLI application) process is killed as soon as the command execution ends. It means carthage does not hold in memory state (the static properties) between the command executions. That's why I introduced UserDefaults - to keep the state of the application between the command executions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer option one.

But failing that, I think we should keep the last fetched time in a file on disk in the dependencies directory. Users sometimes delete the entire cache to get back to a clean state. I'd prefer to keep all the cache info in that directory instead of putting some of it in user defaults.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👋 @mdiep

I was investigating option one and unfortunately couldn't find a reasonable solution.

I was playing with with the option number two - file solution. I'd suggest to modify FetchCache component and convert it from in-process caching to persistent caching. We could store last fetch timestamp per dependency (../Library/Caches/org.carthage.CarthageKit/dependencies):

image

Please tell me what you think about this solution 🙇

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we set the last modified date of the directory for the dependency?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, thanks! 👍

Tested on just three dependencies, but already noticed a great improvement (a few seconds):

Screenshot 2019-04-01 at 08 03 12

Screenshot 2019-04-01 at 08 03 27

I implemented the changes and kindly ask you for re-review @mdiep 🙇 🙇

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👋 Hey @mdiep 🙂 Just wanted to kindly ask if you did get a chance to have a look at the newest changes? 🙇 🤔

Source/carthage/Outdated.swift Show resolved Hide resolved
if shouldIgnoreFetching {
// TODO: Non-fetching changes required.
carthage.println("The dependencies will not be fetched due to non-expired fetch interval.")
return project.outdatedDependencies(options.isVerbose)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just set FetchCache.fetchCacheInterval to the value that's passed in. That should be all you need to do?

@mollyIV mollyIV changed the title [WIP] Add fetch-interval to outdated command to skip fetching the dependencies Add fetch-interval to outdated command to skip fetching the dependencies Mar 7, 2019
@mollyIV mollyIV force-pushed the carthage-outdated-skip-fetching-dependencies branch from 86a4d9d to 16a2b51 Compare April 1, 2019 06:25
@mollyIV mollyIV marked this pull request as ready for review April 1, 2019 06:28
@jdhealy jdhealy self-requested a review April 1, 2019 06:36
@mollyIV
Copy link
Contributor Author

mollyIV commented Apr 17, 2019

👋 @jdhealy

Thanks for adding yourself as a reviewer 🙇 Please let me know if you have any questions about the implementation 👍

@jdhealy
Copy link
Member

jdhealy commented Apr 24, 2019

It's my first Carthage contribution 🎉

High five over the internet Thanks, so much!

I've got time for one or two notes before I head out the door this morning.

fileprivate static func repositoriesLastFetchTime() -> Date? {
do {
let attr = try FileManager.default.attributesOfItem(atPath: Constants.Dependency.repositoriesURL.path)
return attr[FileAttributeKey.modificationDate] as? Date
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For us relying on file system modification date here — there's far too many antivirus scanners and cloud storage sync tools that continually just modify large swaths of files for me to be comfortable with this 😕

Maybe our own xattr (extended attribute), could work? I'll try to give some thought to this later…

Copy link
Contributor Author

@mollyIV mollyIV Apr 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your suggestion @jdhealy 🙇 I updated the code - now we are using custom extended attribute instead of modification date attribute 💪

Screenshot 2019-04-27 at 17 36 54

Could you please have a 👀 🙏

EDIT: Noticed CI job has failed, but it seems like a global issue. It happened for other pull requests as well 🤔

@tmspzz
Copy link
Member

tmspzz commented May 20, 2019

@mollyIV It doesn't look like this PR is building. Do you have time to follow up?

@mollyIV
Copy link
Contributor Author

mollyIV commented May 20, 2019

👋 @blender ,
It might be a global issue #2780 - I saw many PRs with failing tests.

Will do the master rebase 👍

@mollyIV mollyIV force-pushed the carthage-outdated-skip-fetching-dependencies branch from fc5440d to bfca280 Compare May 20, 2019 15:55
@mollyIV
Copy link
Contributor Author

mollyIV commented May 21, 2019

Hey @blender,
I did the rebase however the tests are still failing. I compered the CI_INTEGRATION_TESTS from this MR

image

and the error log seems to be the same.

Any hint what that could relate to?
Shall we create a new issue about fixing those? (seems a global issue)

🤔

@stale
Copy link

stale bot commented Jun 20, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jun 20, 2019
@mollyIV
Copy link
Contributor Author

mollyIV commented Jun 20, 2019

Hey guys 👋

Any news about a CI issue? 🤔 Could anyone try to re-run it? 🙏

@stale stale bot removed the stale label Jun 20, 2019
@stale

This comment has been minimized.

@stale stale bot added the stale label Jul 20, 2019
@mollyIV

This comment has been minimized.

@stale stale bot removed the stale label Jul 22, 2019
@mollyIV mollyIV force-pushed the carthage-outdated-skip-fetching-dependencies branch from bfca280 to 3796768 Compare July 29, 2019 18:02
@stale
Copy link

stale bot commented Aug 28, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Aug 28, 2019
@mollyIV
Copy link
Contributor Author

mollyIV commented Sep 2, 2019

👋@Stale, still in review.

@stale stale bot removed the stale label Sep 2, 2019
@stale
Copy link

stale bot commented Oct 2, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Oct 2, 2019
@mollyIV
Copy link
Contributor Author

mollyIV commented Oct 2, 2019

ping stale 🤖

@stale stale bot removed the stale label Oct 2, 2019
@stale
Copy link

stale bot commented Nov 1, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 1, 2019
@mollyIV
Copy link
Contributor Author

mollyIV commented Nov 1, 2019

ping stale

@stale stale bot removed the stale label Nov 1, 2019
@stale
Copy link

stale bot commented Dec 1, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Dec 1, 2019
@stale stale bot closed this Dec 8, 2019
@@ -22,13 +22,12 @@ public struct FetchCache {
lastFetchTimes.removeAll()
}

internal static func needsFetch(forURL url: GitURL) -> Bool {
guard let lastFetch = lastFetchTimes[url] else {
internal static func needsFetch(forURL url: GitURL) -> Bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carthage uses tabs instead of spaces for indentation -- could you please reformat your changes to do the same?

return true
}

let difference = Date().timeIntervalSince1970 - lastFetch

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please revert this change?

}

func extendedAttribute(for name: String) throws -> Data {
let data = try withUnsafeFileSystemRepresentation { path -> Data in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious -- what are your thoughts on using this approach rather than using the methods provided by NSFileManager? I've never used either personally.

https://developer.apple.com/documentation/foundation/filemanager/1413667-setattributes

https://developer.apple.com/documentation/foundation/filemanager/1410452-attributesofitem

@tmspzz tmspzz reopened this Dec 8, 2019
@stale stale bot removed the stale label Dec 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants