예제 #1
0
        public Task ExecuteAsync(object?parameter = null, CancellationToken cancellation = default)
        {
            var dialog = new MessageBox(
                string.Format("Reset"),
                DialogBoxButton.Ok | DialogBoxButton.Cancel,
                "We will (hard) reset the current checked out branch to its corresponding remote tip");

            if (mainThread.Invoke(() => dialog.ShowDialog()) == true)
            {
                foreach (var(config, repository, index) in repositories.Select((config, index) => (config, config.Repository, index)))
                {
                    repository.Fetch(credentials, prune: true);

                    if (repository.GetBranch(config.TargetBranchRemote) is Branch targetBranchRemote)
                    {
                        repository.Reset(ResetMode.Hard, targetBranchRemote.Tip);

                        eventStream.Push(Status.Create(
                                             (index + 1) / (float)repositories.Count(),
                                             "Resetting {0} to {1}...", repository.GetName(), targetBranchRemote.FriendlyName));
                    }
                }

                eventStream.Push(Status.Succeeded());

                mainThread.Invoke(() => view.Refresh());
            }

            return(Task.CompletedTask);
        }
예제 #2
0
 public void Connect(IEventStream stream)
 {
     subscription = stream.Of<IEventPattern<IDevice, ISensed>>().Subscribe(sensed =>
     {
         var type = topicRegistry.Find(sensed.EventArgs.Topic);
         switch (type)
         {
             case TopicType.Boolean:
                 stream.Push(sensed.Sender, Impulse.Create(sensed.EventArgs.Topic, Payload.ToBoolean(sensed.EventArgs.Payload), clock.Now));
                 break;
             case TopicType.Number:
                 stream.Push(sensed.Sender, Impulse.Create(sensed.EventArgs.Topic, Payload.ToNumber(sensed.EventArgs.Payload), clock.Now));
                 break;
             case TopicType.String:
                 stream.Push(sensed.Sender, Impulse.Create(sensed.EventArgs.Topic, Payload.ToString(sensed.EventArgs.Payload), clock.Now));
                 break;
             case TopicType.Void:
                 stream.Push(sensed.Sender, Impulse.Create(sensed.EventArgs.Topic, Unit.Default, clock.Now));
                 break;
             case TopicType.Unknown:
             default:
                 // TODO: throw? Report?
                 break;
         }
     });
 }
예제 #3
0
파일: GitRepository.cs 프로젝트: kzu/guit
        public void UpdateSubmodules(bool recursive = true, IEventStream?eventStream = null)
        {
            foreach (var submodule in repository.Submodules)
            {
                eventStream?.Push(Status.Create("Submodule update {0}", submodule.Name));

                try
                {
                    repository.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions()
                    {
                        Init = true
                    });

                    if (recursive)
                    {
                        using (var subRepository = new GitRepository(Path.Combine(repository.Info.WorkingDirectory, submodule.Path)))
                            subRepository.UpdateSubmodules(eventStream: eventStream);
                    }
                }
                catch
                {
                    eventStream?.Push(Status.Create("Failed to update submodule {0}", submodule.Name));
                }
            }
        }
        private static IDisposable RegisterService <TEvent>(
            this IEventStream eventStream,
            Action onStart,
            Action onStop,
            Action onPrepare       = null,
            Action <TEvent> onNext = null,
            string name            = null)
        {
            var disposables = new CompositeDisposable(capacity: 4);

            if (onNext != null)
            {
                eventStream
                .OfType <TEvent>()
                .Subscribe(onNext)
                .DisposeWith(disposables);
            }

            if (onPrepare != null)
            {
                eventStream
                .OfType <IRequestFor <TEvent> >()
                .Subscribe(_ => onPrepare())
                .DisposeWith(disposables);
            }

            if (onStart != null)
            {
                eventStream
                .OfType <ISubscriptionOf <TEvent> >()
                .Subscribe(_ =>
                {
                    onStart();

                    eventStream.Push(new ServiceStartedEvent(name));
                })
                .DisposeWith(disposables);
            }

            if (onStop == null)
            {
                eventStream
                .OfType <IUnsubscriptionOf <TEvent> >()
                .Subscribe(_ =>
                {
                    onStop();

                    eventStream.Push(new ServiceStoppedEvent(name));
                })
                .DisposeWith(disposables);
            }

            eventStream.Push(new ServiceRegisteredEvent(name));

            return(disposables);
        }
예제 #5
0
 public void Connect(IEventStream stream)
 {
     subscription = new CompositeDisposable(
         stream.Of<ICommand<bool>>().Subscribe(cmd =>
             stream.Push(Command.Create(cmd.Topic, Payload.ToBytes(cmd.Payload), cmd.Timestamp, cmd.TargetDeviceIds))),
         stream.Of<ICommand<float>>().Subscribe(cmd =>
             stream.Push(Command.Create(cmd.Topic, Payload.ToBytes(cmd.Payload), cmd.Timestamp, cmd.TargetDeviceIds))),
         stream.Of<ICommand<string>>().Subscribe(cmd =>
             stream.Push(Command.Create(cmd.Topic, Payload.ToBytes(cmd.Payload), cmd.Timestamp, cmd.TargetDeviceIds))),
         stream.Of<ICommand<Unit>>().Subscribe(cmd =>
             stream.Push(Command.Create(cmd.Topic, new byte[0], cmd.Timestamp, cmd.TargetDeviceIds))));
 }
예제 #6
0
파일: FetchCommand.cs 프로젝트: kzu/guit
        public Task ExecuteAsync(CancellationToken cancellation = default)
        {
            var remotes = repository.Network.Remotes.ToList();

            foreach (var remote in remotes)
            {
                eventStream.Push(Status.Create((remotes.IndexOf(remote) + 1f) / (remotes.Count + 1f), "Fetching {0}...", remote.Name));

                repository.Fetch(remote, credentials, eventStream);
            }

            eventStream.Push(Status.Succeeded());

            return(Task.CompletedTask);
        }
예제 #7
0
파일: CommitCommand.cs 프로젝트: kzu/guit
        void CommitChanges(IGitRepository repository, IEnumerable <StatusEntry> entries, CommitDialog dialog)
        {
            if (mainThread.ShowDialog(dialog) == true)
            {
                if (!string.IsNullOrEmpty(dialog.NewBranchName))
                {
                    repository.Checkout(repository.CreateBranch(dialog.NewBranchName));
                }

                foreach (var entry in entries)
                {
                    repository.Stage(entry.FilePath);
                }

                eventStream.Push <Status>(0.5f);

                var signature = repository.Config.BuildSignature(DateTimeOffset.Now);

                repository.Commit(
                    dialog.Message,
                    signature,
                    signature,
                    CreateCommitOptions());
            }
        }
예제 #8
0
파일: FetchCommand.cs 프로젝트: kzu/guit
        public Task ExecuteAsync(CancellationToken cancellation = default)
        {
            foreach (var(config, index) in repositories.Select((config, index) => (config, index)))
            {
                eventStream.Push(Status.Create((index + 1) / (float)repositories.Count(), "Fetching {0}...", config.Repository.GetName()));

                config.Repository.Fetch(credentials, prune: true);
            }
            ;

            eventStream.Push(Status.Succeeded());

            mainThread.Invoke(() => view.Refresh());

            return(Task.CompletedTask);
        }
예제 #9
0
        public async Task ExecuteAsync(object?parameter = null, CancellationToken cancellation = default)
        {
            foreach (var repositoryEntries in view.MarkedEntries.GroupBy(x => x.Config).Where(x => x.Any()))
            {
                var config     = repositoryEntries.Key;
                var repository = config.Repository;

                var dialog = new MessageBox(
                    string.Format("{0} ({1} -> {2})", config.Repository.GetName(), config.BaseBranch, config.TargetBranch),
                    DialogBoxButton.Ok | DialogBoxButton.Cancel,
                    string.Format("We will cherry pick the selected {0} commit(s) into the following branch: {1}", repositoryEntries.Count(), config.TargetBranch));

                if (mainThread.Invoke(() => dialog.ShowDialog()) == true)
                {
                    var targetBranch = repository.SwitchToTargetBranch(config);

                    var count = 0;
                    foreach (var entry in repositoryEntries.Reverse())
                    {
                        var result = repository.CherryPick(entry.Commit, repository.Config.BuildSignature(DateTimeOffset.Now));

                        if (result.Status == CherryPickStatus.Conflicts)
                        {
                            await commandService.RunAsync(WellKnownCommands.ResolveConflicts, cancellation : cancellation);

                            if (repository.Index.Conflicts.Any())
                            {
                                repository.Reset(ResetMode.Hard);
                                throw new InvalidOperationException(string.Format("Unable to cherry pick {0}", entry.Commit.MessageShort));
                            }
                            else
                            {
                                // TODO: auto-commit, keep moving
                            }

                            eventStream.Push(Status.Create(++count / (float)repositoryEntries.Count(), "Cherry picking {0} {1}", entry.Commit.GetShortSha(), entry.Commit.MessageShort));
                        }
                        else
                        {
                            eventStream.Push(Status.Create(++count / (float)repositoryEntries.Count(), "Cherry picking {0} {1}", entry.Commit.GetShortSha(), entry.Commit.MessageShort));
                        }
                    }

                    mainThread.Invoke(() => view.Refresh());
                }
            }
        }
 /// <summary>
 /// Pushes a string the given <see cref="IEventStream"/>
 /// with an associated payload
 /// </summary>
 public static void Push <TPayload>(
     this IEventStream eventStream,
     string name,
     TPayload payload) =>
 eventStream.Push(new StringEvent <TPayload>
 {
     Name    = name,
     Payload = payload
 });
예제 #11
0
        public Task ExecuteAsync(object?parameter = null, CancellationToken cancellation = default)
        {
            var dirtyRepositories = repositories
                                    .Select(config => (
                                                config,
                                                targetBranch: config.Repository.GetBranch(config.TargetBranch),
                                                targetBranchRemote: config.Repository.GetBranch(config.TargetBranchRemote)))
                                    .Where(x => x.targetBranch != null && x.targetBranch.Tip != x.targetBranchRemote?.Tip)
                                    .Select(x => (x.config.Repository.GetName(), x.config.TargetBranchRemote + $"-merge-{x.targetBranch.Tip.GetShortSha()}"));

            if (dirtyRepositories.Any())
            {
                var dialog = new PushDialog(dirtyRepositories.ToArray());

                if (mainThread.Invoke(() => dialog.ShowDialog()) == true)
                {
                    foreach (var branch in dialog.Branches)
                    {
                        if (branch.BranchName?.Contains('/') == true && repositories.FirstOrDefault(x => x.Repository.GetName() == branch.Repo) is CherryPickConfig config)
                        {
                            var repository = config.Repository;
                            var remoteName = branch.BranchName.Substring(0, branch.BranchName.IndexOf('/'));

                            if (repository.Network.Remotes.FirstOrDefault(x => x.Name == remoteName) is Remote remote)
                            {
                                var targetBranchName = branch.BranchName.Substring(remoteName.Length + 1);

                                // Push
                                config.Repository.Network.Push(
                                    repository.Network.Remotes.Single(x => x.Name == "origin"),
                                    $"refs/heads/{repository.Head.FriendlyName}:refs/heads/{targetBranchName}",
                                    new PushOptions {
                                    CredentialsProvider = credentials
                                });

                                eventStream.Push(Status.Create("Pushed changes to {0}", $"{repository.GetRepoUrl()}/tree/{targetBranchName}"));

                                Process.Start("cmd", $"/c start {repository.GetRepoUrl()}/compare/{config.TargetBranch}...{targetBranchName}");

                                mainThread.Invoke(() => view.Refresh());
                            }
                            else
                            {
                                mainThread.Invoke(() => new MessageBox("Error", "Remote '{0}' not found for '{1}'", remoteName, branch.BranchName).ShowDialog());
                            }
                        }
                    }
                }
            }

            return(Task.CompletedTask);
        }
예제 #12
0
        public void Connect(IEventStream stream)
        {
            subscription = clock.Tick.Subscribe(tick =>
            {
                stream.Push(Impulse.Create(Topics.System.Date, tick, clock.Now));
                stream.Push(Impulse.Create(Topics.System.Day, tick.Day, clock.Now));
                stream.Push(Impulse.Create(Topics.System.Month, tick.Month, clock.Now));
                stream.Push(Impulse.Create(Topics.System.Year, tick.Year, clock.Now));

                stream.Push(Impulse.Create(Topics.System.Time, new TimeSpan(tick.Hour, tick.Minute, tick.Second), clock.Now));
                stream.Push(Impulse.Create(Topics.System.Hour, tick.Hour, clock.Now));
                stream.Push(Impulse.Create(Topics.System.Minute, tick.Minute, clock.Now));
                stream.Push(Impulse.Create(Topics.System.Second, tick.Second, clock.Now));
            });
        }
예제 #13
0
파일: GitRepository.cs 프로젝트: kzu/guit
 public void Fetch(IEnumerable <Remote> remotes, CredentialsHandler credentials, IEventStream?eventStream = null, bool prune = false)
 {
     foreach (var remote in remotes)
     {
         Git.Fetch(
             (Repository)repository,
             remote.Name,
             remote.FetchRefSpecs.Select(x => x.Specification), new FetchOptions
         {
             Prune = prune,
             CredentialsProvider = credentials,
             OnProgress          = serverProgressOutput =>
             {
                 eventStream?.Push(new Status(serverProgressOutput));
                 return(true);
             },
             OnTransferProgress = progress =>
             {
                 eventStream?.Push(new Status($"Received {progress.ReceivedObjects} of {progress.TotalObjects}", progress.ReceivedObjects / (float)progress.TotalObjects));
                 return(true);
             }
         }, string.Empty);
     }
 }
예제 #14
0
        TView CreateDialogImpl <TView>() where TView : IDialogWindow, new()
        {
            var dialog = new TView();

            if (dialog is Window dialogWindow)
            {
                jtf.Run(async() =>
                {
                    await jtf.SwitchToMainThreadAsync();
                    ErrorHandler.ThrowOnFailure(uiShell.GetValue().GetDialogOwnerHwnd(out var owner));
                    new WindowInteropHelper(dialogWindow).Owner = owner;
                    dialogWindow.WindowStartupLocation          = WindowStartupLocation.CenterOwner;
                    dialogWindow.ShowInTaskbar = false;
                });

                eventStream.Push(new DialogCreated(dialog));
            }

            return(dialog);
        }
예제 #15
0
        void Commit(IRepository repository, IEnumerable <StatusEntry> entries, string title = "Commit", bool reportProgress = false)
        {
            if (entries.Any() || Amend)
            {
                var dialog = new CommitDialog(title);

                if (Amend)
                {
                    dialog.Message = repository.Commits.FirstOrDefault()?.Message;
                }

                if (mainThread.Invoke(() => dialog.ShowDialog()) == true)
                {
                    if (!string.IsNullOrEmpty(dialog.NewBranchName))
                    {
                        repository.Checkout(repository.CreateBranch(dialog.NewBranchName));
                    }

                    foreach (var entry in entries)
                    {
                        repository.Stage(entry.FilePath);
                    }

                    var signature = repository.Config.BuildSignature(DateTimeOffset.Now);

                    var options = new CommitOptions
                    {
                        AmendPreviousCommit = Amend
                    };

                    eventStream.Push <Status>(0.5f);

                    repository.Commit(dialog.Message, signature, signature, options);
                }
            }
        }
예제 #16
0
 /// <summary>
 /// Pushes the given event with the sender information in the
 /// form of an <see cref="IEventPattern{TEvent}"/>.
 /// </summary>
 /// <typeparam name="TEvent">The type of the event, typically inferred from the passed-in argument.</typeparam>
 /// <param name="stream">The event stream to push to.</param>
 /// <param name="sender">The sender of the event.</param>
 /// <param name="event">The event data.</param>
 public static void Push <TEvent>(this IEventStream stream, object sender, TEvent @event)
 {
     stream.Push(EventPattern.Create(sender, @event));
 }
예제 #17
0
        public Task ExecuteAsync(object?parameter = null, CancellationToken cancellation = default)
        {
            var dialog = new SwitchDialog(branches: repository.Branches.Select(x => x.FriendlyName).OrderBy(x => x).ToArray());

            if (mainThread.Invoke(() => dialog.ShowDialog()) == true && !string.IsNullOrEmpty(dialog.Branch))
            {
                var branch = repository.Branches.FirstOrDefault(x => x.FriendlyName == dialog.Branch);

                var targetBranch          = branch;
                var targetBranchName      = dialog.Branch;
                var overwriteTargetBranch = false;

                // Check if the selected branch is remote
                if (branch?.IsRemote == true)
                {
                    // Get the branch name from the remote
                    targetBranchName = branch.GetName();

                    // Allow the user to create a branch for the remote
                    var createBranchDialog = new InputBox("Create Branch", "Branch")
                    {
                        Text = targetBranchName
                    };
                    if (mainThread.Invoke(() => createBranchDialog.ShowDialog()) == true)
                    {
                        // Check if the new branch already exists
                        targetBranchName = createBranchDialog.Text;
                        targetBranch     = repository.Branches.FirstOrDefault(x =>
                                                                              !x.IsRemote && x.FriendlyName == createBranchDialog.Text);

                        if (targetBranch != null)
                        {
                            // The branch already exist => ask the user to overwrite it
                            var forceDialog = new MessageBox(
                                "Warning",
                                DialogBoxButton.Ok | DialogBoxButton.Cancel,
                                "A branch with this name already exists. Do you want to overwrite it?");

                            overwriteTargetBranch = mainThread.Invoke(() => forceDialog.ShowDialog() == true);
                            if (!overwriteTargetBranch)
                            {
                                return(CancelCheckout());
                            }
                        }
                    }
                    else
                    {
                        return(CancelCheckout());
                    }
                }

                // 1. Check the remote branch if remote was selected
                if (branch?.IsRemote == true)
                {
                    repository.Checkout(branch);
                }

                // 2. Remove the existing branch if the user decided to overwrite it
                if (overwriteTargetBranch && targetBranch != null)
                {
                    eventStream.Push(Status.Create(0.2f, "Removing branch {0}", targetBranch.FriendlyName));
                    repository.Branches.Remove(targetBranch);
                }

                // 3. Create the branch if it does not exist
                if (targetBranch == null)
                {
                    eventStream.Push(Status.Create(0.4f, "Creating branch {0}", targetBranchName));
                    targetBranch = repository.CreateBranch(targetBranchName);
                }

                // 4. Checkout the branch
                eventStream.Push(Status.Create(0.6f, "Swithing to branch {0}", targetBranchName));
                repository.Checkout(targetBranch);

                // 5. Update submodules
                if (dialog.UpdateSubmodules)
                {
                    eventStream.Push(Status.Create(0.8f, "Updating submodules..."));
                    repository.UpdateSubmodules(eventStream: eventStream);
                }

                eventStream.Push(new BranchChanged(targetBranchName));
                eventStream.Push(Status.Succeeded());
            }

            return(Task.CompletedTask);
        }
예제 #18
0
 /// <summary>
 /// Pushes a new instance of <typeparamref name="TEvent"/> through the stream.
 /// </summary>
 public static void Push <TEvent>(this IEventStream events) where TEvent : new()
 => events.Push(new TEvent());
예제 #19
0
        public Task ExecuteAsync(CancellationToken cancellation = default)
        {
            var localBranch  = repository.Head;
            var targetBranch = repository.Head.TrackedBranch ?? repository.Head;

            var dialog = new PushDialog(
                targetBranch.RemoteName ?? repository.GetDefaultRemoteName(),
                targetBranch.GetName(),
                trackRemoteBranch: repository.Head.TrackedBranch != null,
                remotes: repository.GetRemoteNames(),
                branches: repository.GetBranchNames());

            var result = mainThread.Invoke(() => dialog.ShowDialog());

            if (result == true && !string.IsNullOrEmpty(dialog.Remote))
            {
                var remote = repository
                             .Network
                             .Remotes
                             .FirstOrDefault(x => x.Name == dialog.Remote);

                if (remote != null)
                {
                    var pushRefSpec = $"refs/heads/{localBranch.GetName()}:refs/heads/{dialog.Branch}";
                    if (dialog.Force)
                    {
                        pushRefSpec = "+" + pushRefSpec;
                    }

                    var pushOptions = new PushOptions()
                    {
                        CredentialsProvider    = credentialsProvider,
                        OnPushTransferProgress = (current, total, bytes) =>
                        {
                            eventStream.Push <Status>((float)current / (float)total);
                            return(true);
                        }
                    };

                    eventStream.Push(Status.Start("git push {0} {1}", dialog.Remote, pushRefSpec));

                    repository.Network.Push(remote, pushRefSpec, pushOptions);

                    if (dialog.TrackRemoteBranch)
                    {
                        var trackedBranch = repository.Branches.FirstOrDefault(x =>
                                                                               x.RemoteName == dialog.Remote && x.GetName() == dialog.Branch);

                        if (trackedBranch != null)
                        {
                            localBranch.Track(repository, trackedBranch);
                        }
                    }

                    eventStream.Push(Status.Succeeded());

                    mainThread.Invoke(() => view.Refresh());
                }
            }

            return(Task.CompletedTask);
        }
예제 #20
0
        public async Task ExecuteAsync(object?parameter = null, CancellationToken cancellation = default)
        {
            var repositoryStatus = repository.RetrieveStatus();

            var localBranch  = repository.Head;
            var targetBranch = repository.Head.TrackedBranch ?? repository.Head;

            var dialog = new PullDialog(
                targetBranch.RemoteName ?? repository.GetDefaultRemoteName(),
                targetBranch.GetName(),
                showStashWarning: repositoryStatus.IsDirty,
                trackRemoteBranch: false,
                remotes: repository.GetRemoteNames(),
                branches: repository.GetBranchNames());

            if (mainThread.Invoke(() => dialog.ShowDialog()) == true && !string.IsNullOrEmpty(dialog.Branch))
            {
                var targetBranchFriendlyName = string.IsNullOrEmpty(dialog.Remote) ?
                                               dialog.Branch : $"{dialog.Remote}/{dialog.Branch}";

                targetBranch = repository.Branches.FirstOrDefault(x => x.FriendlyName == targetBranchFriendlyName);

                if (targetBranch == null)
                {
                    throw new InvalidOperationException(string.Format("Branch {0} not found", targetBranchFriendlyName));
                }

                eventStream.Push(Status.Start("Pull {0} {1}", targetBranchFriendlyName, dialog.IsFastForward ? "With Fast Fordward" : string.Empty));

                var stash       = default(Stash);
                var mergeResult = default(MergeResult);
                var stashResult = default(StashApplyStatus);

                // 1. Fetch
                if (targetBranch.IsRemote)
                {
                    TryFetch(targetBranch);
                }

                // 2. Stash (optional, if the repo is dirty) and Merge
                try
                {
                    if (repositoryStatus.IsDirty)
                    {
                        stash = repository.Stashes.Add(Signatures.GetStashSignature(), StashModifiers.IncludeUntracked);
                    }

                    mergeResult = Merge(targetBranch, dialog.IsFastForward);
                }
                finally
                {
                    if (stash != null && repository.Stashes.Contains(stash) && !repository.RetrieveStatus().IsDirty)
                    {
                        stashResult = repository.Stashes.Pop(repository.Stashes.ToList().IndexOf(stash));
                    }
                }

                // 3. Resolve conflicts
                if (mergeResult?.Status == MergeStatus.Conflicts)
                {
                    await commandService.RunAsync("ResolveConflicts");
                }

                // 4. Track
                if (dialog.TrackRemoteBranch)
                {
                    localBranch.Track(repository, targetBranch);
                }

                // 5. Update submodules
                if (dialog.UpdateSubmodules)
                {
                    eventStream.Push(Status.Create(0.8f, "Updating submodules..."));
                    repository.UpdateSubmodules(eventStream: eventStream);
                }

                eventStream.Push(Status.Finish(mergeResult.Status.ToString()));

                mainThread.Invoke(() => view.Refresh());
            }
        }