Welcome to mirror list, hosted at ThFree Co, Russian Federation.

RemoteCallbacks.cs « LibGit2Sharp - github.com/mono/libgit2sharp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 47a15dc67f820629c1536954edcba85d6fc2f513 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
using System;
using LibGit2Sharp.Core;
using LibGit2Sharp.Handlers;

namespace LibGit2Sharp
{
    /// <summary>
    /// Class to translate libgit2 callbacks into delegates exposed by LibGit2Sharp.
    /// Handles generating libgit2 git_remote_callbacks datastructure given a set
    /// of LibGit2Sharp delegates and handles propagating libgit2 callbacks into
    /// corresponding LibGit2Sharp exposed delegates.
    /// </summary>
    internal class RemoteCallbacks
    {
        internal RemoteCallbacks(CredentialsHandler credentialsProvider)
        {
            CredentialsProvider = credentialsProvider;
        }

        internal RemoteCallbacks(PushOptions pushOptions)
        {
            if (pushOptions == null)
            {
                return;
            }

            PushTransferProgress = pushOptions.OnPushTransferProgress;
            PackBuilderProgress = pushOptions.OnPackBuilderProgress;
            CredentialsProvider = pushOptions.CredentialsProvider;
        }

        internal RemoteCallbacks(FetchOptionsBase fetchOptions)
        {
            if (fetchOptions == null)
            {
                return;
            }

            Progress = fetchOptions.OnProgress;
            DownloadTransferProgress = fetchOptions.OnTransferProgress;
            UpdateTips = fetchOptions.OnUpdateTips;
            CredentialsProvider = fetchOptions.CredentialsProvider;
        }

        #region Delegates

        /// <summary>
        /// Progress callback. Corresponds to libgit2 progress callback.
        /// </summary>
        private readonly ProgressHandler Progress;

        /// <summary>
        /// UpdateTips callback. Corresponds to libgit2 update_tips callback.
        /// </summary>
        private readonly UpdateTipsHandler UpdateTips;

        /// <summary>
        /// Managed delegate to be called in response to a git_transfer_progress_callback callback from libgit2.
        /// This will in turn call the user provided delegate.
        /// </summary>
        private readonly TransferProgressHandler DownloadTransferProgress;

        /// <summary>
        /// Push transfer progress callback.
        /// </summary>
        private readonly PushTransferProgressHandler PushTransferProgress;

        /// <summary>
        /// Pack builder creation progress callback.
        /// </summary>
        private readonly PackBuilderProgressHandler PackBuilderProgress;

        #endregion

        /// <summary>
        /// The credentials to use for authentication.
        /// </summary>
        private readonly CredentialsHandler CredentialsProvider;

        internal GitRemoteCallbacks GenerateCallbacks()
        {
            var callbacks = new GitRemoteCallbacks {version = 1};

            if (Progress != null)
            {
                callbacks.progress = GitProgressHandler;
            }

            if (UpdateTips != null)
            {
                callbacks.update_tips = GitUpdateTipsHandler;
            }

            if (CredentialsProvider != null)
            {
                callbacks.acquire_credentials = GitCredentialHandler;
            }

            if (DownloadTransferProgress != null)
            {
                callbacks.download_progress = GitDownloadTransferProgressHandler;
            }

            if (PushTransferProgress != null)
            {
                callbacks.push_transfer_progress = GitPushTransferProgressHandler;
            }

            if (PackBuilderProgress != null)
            {
                callbacks.pack_progress = GitPackbuilderProgressHandler;
            }

            return callbacks;
        }

        #region Handlers to respond to callbacks raised by libgit2

        /// <summary>
        /// Handler for libgit2 Progress callback. Converts values
        /// received from libgit2 callback to more suitable types
        /// and calls delegate provided by LibGit2Sharp consumer.
        /// </summary>
        /// <param name="str">IntPtr to string from libgit2</param>
        /// <param name="len">length of string</param>
        /// <param name="data">IntPtr to optional payload passed back to the callback.</param>
        /// <returns>0 on success; a negative value to abort the process.</returns>
        private int GitProgressHandler(IntPtr str, int len, IntPtr data)
        {
            ProgressHandler onProgress = Progress;

            bool shouldContinue = true;

            if (onProgress != null)
            {
                string message = LaxUtf8Marshaler.FromNative(str, len);
                shouldContinue = onProgress(message);
            }

            return Proxy.ConvertResultToCancelFlag(shouldContinue);
        }

        /// <summary>
        /// Handler for libgit2 update_tips callback. Converts values
        /// received from libgit2 callback to more suitable types
        /// and calls delegate provided by LibGit2Sharp consumer.
        /// </summary>
        /// <param name="str">IntPtr to string</param>
        /// <param name="oldId">Old reference ID</param>
        /// <param name="newId">New referene ID</param>
        /// <param name="data">IntPtr to optional payload passed back to the callback.</param>
        /// <returns>0 on success; a negative value to abort the process.</returns>
        private int GitUpdateTipsHandler(IntPtr str, ref GitOid oldId, ref GitOid newId, IntPtr data)
        {
            UpdateTipsHandler onUpdateTips = UpdateTips;
            bool shouldContinue = true;

            if (onUpdateTips != null)
            {
                string refName = LaxUtf8Marshaler.FromNative(str);
                shouldContinue = onUpdateTips(refName, oldId, newId);
            }

            return Proxy.ConvertResultToCancelFlag(shouldContinue);
        }

        /// <summary>
        /// The delegate with the signature that matches the native git_transfer_progress_callback function's signature.
        /// </summary>
        /// <param name="progress"><see cref="GitTransferProgress"/> structure containing progress information.</param>
        /// <param name="payload">Payload data.</param>
        /// <returns>the result of the wrapped <see cref="TransferProgressHandler"/></returns>
        private int GitDownloadTransferProgressHandler(ref GitTransferProgress progress, IntPtr payload)
        {
            bool shouldContinue = true;

            if (DownloadTransferProgress != null)
            {
                shouldContinue = DownloadTransferProgress(new TransferProgress(progress));
            }

            return Proxy.ConvertResultToCancelFlag(shouldContinue);
        }

        private int GitPushTransferProgressHandler(uint current, uint total, UIntPtr bytes, IntPtr payload)
        {
            bool shouldContinue = true;

            if (PushTransferProgress != null)
            {
                shouldContinue = PushTransferProgress((int)current, (int)total, (long)bytes);
            }

            return Proxy.ConvertResultToCancelFlag(shouldContinue);
        }

        private int GitPackbuilderProgressHandler(int stage, uint current, uint total, IntPtr payload)
        {
            bool shouldContinue = true;

            if (PackBuilderProgress != null)
            {
                shouldContinue = PackBuilderProgress((PackBuilderStage)stage, (int)current, (int)total);
            }

            return Proxy.ConvertResultToCancelFlag(shouldContinue);
        }

        private int GitCredentialHandler(out IntPtr ptr, IntPtr cUrl, IntPtr usernameFromUrl, GitCredentialType credTypes, IntPtr payload)
        {
            string url = LaxUtf8Marshaler.FromNative(cUrl);
            string username = LaxUtf8Marshaler.FromNative(usernameFromUrl);

            SupportedCredentialTypes types = default(SupportedCredentialTypes);
            if (credTypes.HasFlag(GitCredentialType.UserPassPlaintext))
            {
                types |= SupportedCredentialTypes.UsernamePassword;
            }
            if (credTypes.HasFlag(GitCredentialType.Default))
            {
                types |= SupportedCredentialTypes.Default;
            }

            var cred = CredentialsProvider(url, username, types);

            return cred.GitCredentialHandler(out ptr);
        }

        #endregion
    }
}