Skip to content

Bind the methods for refspecs #1249

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

Closed
wants to merge 8 commits into from
Closed

Bind the methods for refspecs #1249

wants to merge 8 commits into from

Conversation

carlosmn
Copy link
Member

Refspecs are more than just a few fields. They contain the logic to transform reference names forward and backward. This is something we need when we want to figure out which refspecs go where and figure out e.g. if we're pushing on to a branch which has moved since we last fetched.

This means we need to keep the refspec's memory around, which means we need to keep the remote around. There's maybe a better way to handle us now keeping the memory around than freeing in the destructor (does making Repository disposable break compat?) but it's about freeing memory, so it's not a bad place.

@carlosmn carlosmn force-pushed the cmn/refspec-transform branch from 7ae1e64 to dd87dc6 Compare December 14, 2015 21:04
@ethomson
Copy link
Member

(does making Repository disposable break compat?)

Repository is IDisposable already. Did you mean Remote?

@carlosmn
Copy link
Member Author

Yes, I did mean Remote. It's a new thing that's disposable, so existing code wouldn't know to handle it already.

@ethomson
Copy link
Member

I'm in favor of us having more bindings directly to libgit2 and have them be IDisposable. Best to do this before the mythical move towards 1.0.

/cc @whoisj

Edward Thomson and others added 8 commits March 4, 2016 17:56
Bump version number to 0.23 (prerelease)
Refspecs aren't just read-only, we need the objects around for some
operations (added in a later commit). The memory is owned by the remote
object so we need to keep that around as well.
These are actions, so they need the handle which we previously made the
code keep around.
If the user never asks for the refspecs, we should not spend the time and memory
to load them into managed memory.
@carlosmn carlosmn force-pushed the cmn/refspec-transform branch from 87ca2b2 to bd2d6c5 Compare March 7, 2016 09:44
@carlosmn
Copy link
Member Author

carlosmn commented Mar 7, 2016

Merged manually into master.

@carlosmn carlosmn closed this Mar 7, 2016
niik added a commit that referenced this pull request Mar 19, 2016
This is a continuation of #1249. Since Remotes are now disposable we
should eagerly clean up their resources rather than wait for GC to call
the destructor.
@niik niik mentioned this pull request Mar 19, 2016
@niik
Copy link
Contributor

niik commented Mar 19, 2016

I'm in favor of us having more bindings directly to libgit2 and have them be IDisposable

@carlosmn @ethomson I too, am very much in favor of having more IDisposable. But in this case I must say that the API is far from ideal for disposable resources. I just went through all the places in GitHub Desktop where Remotes needed disposing and some of them weren't pretty.

I realize that we're not talking about straight up leaks here but it's common practice to eagerly dispose of any Disposable even though the destructor of the safe handle would do it for you eventually.

Here's some examples from our codebase that I encountered

- RemoteName = libgit2Branch.Remote != null ? libgit2Branch.Remote.Name : null;
+ using (var remote = libgit2Branch.Remote)
+ {
+     RemoteName = remote != null ? remote.Name : null;
+ }
-                        var remote = branch.TrackedBranch;
-                        if (remote != null && remote.Remote.Name != remoteName)
+                        var trackedBranch = branch.TrackedBranch;
+
+                        if (trackedBranch != null)
                         {
-                            branch = null;
+                            using (var remote = trackedBranch.Remote)
+                            {
+                                if (remote.Name != remoteName)
+                                {
+                                    branch = null;
+                                }
+                            }
-                if (!Repository.Network.Remotes.Any())
+                if (!Repository.HasAnyRemotes())

+        public static bool HasAnyRemotes(this IRepository repository)
+        {
+            using (var remote = repository.Network.Remotes.FirstOrDefault())
+            {
+                return remote != null;
+            }
+        }
-                bool hasUpstreamRemote = Repository.Network.Remotes
-                    .Any(x => String.Equals(x.Name, remoteName, StringComparison.OrdinalIgnoreCase));
+                bool hasUpstreamRemote = false;
+                
+                foreach(var remote in Repository.Network.Remotes)
+                {
+                    using(remote)
+                    {
+                        if(String.Equals(remote.Name, remoteName, StringComparison.OrdinalIgnoreCase)) 
+                        {
+                            hasUpstreamRemote = true;
+                            break;
+                        }
+                    }
+                }

Not saying that there's not better ways of doing any of these but I wouldn't expect something coming out of either an enumerator or an indexed property to be disposable is all.

Since it looks like we're eagerly loading everything except the refspecs and seeing as there's usually only one refspec per remote I don't see the big benefit of this approach over copying the data (I can't believe I'm saying this).

@carlosmn
Copy link
Member Author

The advantage here is being able to use the refspecs. They're not just some string, you sometimes actually want to apply them to strings you have. And they're owned by the remote, so you need to keep it around. I'd be in favour of making the Remote load memory less eagerly, this was a first pass to enable some functionality I needed.

@carlosmn
Copy link
Member Author

Looking at your diffs, it looks like what we need is a way to return the name of the remote (i.e. a managed String) in question rather than an instantiated Remote. Even inside the bindings, for some network operations all we want out of the Remote we pass in is the name.

niik added a commit that referenced this pull request Mar 19, 2016
This is a continuation of #1249. Since Remotes are now disposable we
should eagerly clean up their resources rather than wait for GC to call
the destructor.
niik added a commit that referenced this pull request Mar 19, 2016
This is a continuation of #1249. Since Remotes are now disposable we
should eagerly clean up their resources rather than wait for GC to call
the destructor.
niik added a commit that referenced this pull request Mar 23, 2016
This is a continuation of #1249. Since Remotes are now disposable we
should eagerly clean up their resources rather than wait for GC to call
the destructor.
@bording bording deleted the cmn/refspec-transform branch April 21, 2019 02:16
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.

3 participants