Example #1
0
        /// <summary>
        /// Start scanning at the time the form is first shown
        /// </summary>
        private void FormNewRepoScanAddShown(object sender, EventArgs e)
        {
            enableAdd = true;
            int count = 1;

            // Create each of the repos for the selected directories
            foreach (var d in dirs)
            {
                if (enableAdd == false)
                {
                    return;
                }
                try
                {
                    // Update progress bar and make sure it gets painted
                    progressBar.Value = count++;
                    Thread.Sleep(1);

                    textRepo.Text = d;
                    Application.DoEvents();
                    Directory.SetCurrentDirectory(d);
                    if (ClassGit.Run("init").Success() == false)
                    {
                        throw new ClassException("init failed.");
                    }
                    App.Repos.Add(d);
                }
                catch (Exception ex)
                {
                    App.PrintLogMessage("Unable to add repo: " + ex.Message, MessageType.Error);
                    App.PrintStatusMessage(ex.Message, MessageType.Error);
                }
            }
            DialogResult = DialogResult.OK;
        }
Example #2
0
        /// <summary>
        /// Constructor creates a shell executable file that echoes the PASSWORD
        /// environment variable when called. When GIT_ASKPASS is present, Git
        /// obtains a password for its HTTPS operations by calling it.
        /// </summary>
        public ClassGitPasswd()
        {
            // WAR: Do a different kind of shell script dependent on the OS)
            if (ClassUtils.IsMono())
            {
                // Mono: Use the Shell script
                pathPasswordBatchHelper = Path.Combine(App.AppHome, "passwd.sh");
                File.WriteAllText(pathPasswordBatchHelper, "echo $PASSWORD" + Environment.NewLine);

                // Set the execute bit
                if (Exec.Run("chmod", "+x " + pathPasswordBatchHelper).Success() == false)
                {
                    App.PrintLogMessage("ClassGitPasswd: Unable to chmod +x on " + pathPasswordBatchHelper, MessageType.Error);
                }
            }
            else
            {
                // Windows: Use the CMD BAT script
                // Note: Using "App.AppHome" directory to host the batch helper file
                //       fails on XP where that directory has spaces in the name ("Documents and Settings")
                //       which git cannot handle in this context. Similarly, git will fail with
                //       any other path that contains a space.
                // This redirection is used to provide the password in an automated way.
                pathPasswordBatchHelper = Path.Combine(Path.GetTempPath(), "passwd.bat");
                File.WriteAllText(pathPasswordBatchHelper, "@echo %PASSWORD%" + Environment.NewLine);
                pathPasswordBatchHelper = ClassUtils.GetShortPathName(pathPasswordBatchHelper);
            }
            ClassUtils.AddEnvar("GIT_ASKPASS", pathPasswordBatchHelper);

            App.PrintLogMessage("Created HTTP password helper file: " + pathPasswordBatchHelper, MessageType.General);
        }
Example #3
0
        /// <summary>
        /// Open a file browser/Explorer at the specific directory, optionally selecting a file
        /// </summary>
        public static void ExplorerHere(string where, string selFile)
        {
            try
            {
                App.PrintStatusMessage("Opening a file browser at " + where, MessageType.General);

                // WAR: Opening an "Explorer" is platform-specific
                if (IsMono())
                {
                    // TODO: Start a Linux (Ubuntu?) file explorer in a more flexible way
                    Process.Start(@"/usr/bin/nautilus", "--browser " + where);
                }
                else
                {
                    string path = selFile == string.Empty
                                      ? "/e,\"" + where + "\""
                                      : "/e, /select,\"" + selFile + "\"";
                    App.PrintLogMessage(path, MessageType.Command);
                    Process.Start("explorer.exe", path);
                }
            }
            catch (Exception ex)
            {
                App.PrintLogMessage(ex.Message, MessageType.Error);
                MessageBox.Show(ex.Message, "Explorer Here error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
Example #4
0
        /// <summary>
        /// User clicked on the OK button, format the git filter string
        /// </summary>
        private void BtOkClick(object sender, EventArgs e)
        {
            gitFilter = "";

            if (checkBoxMessage.Checked)
            {
                gitFilter += " --grep=\"" + textBoxMessage.Text + "\"";
            }

            if (checkBoxAuthor.Checked)
            {
                gitFilter += " --author=\"" + textBoxAuthor.Text + "\"";
            }

            if (checkBoxBefore.Checked)
            {
                DateTime dt = dateTimeBefore.Value;
                gitFilter += " --before=" + String.Format("{0:yyyy/MM/dd}", dt);
            }

            if (checkBoxAfter.Checked)
            {
                DateTime dt = dateTimeAfter.Value;
                gitFilter += " --after=" + String.Format("{0:yyyy/MM/dd}", dt);
            }

            App.PrintLogMessage("Condition: " + gitFilter, MessageType.General);
        }
Example #5
0
        /// <summary>
        /// Remove given folder and all files and subfolders under it.
        /// If fPreserveGit is true, all folders that are named ".git" will be preserved (not removed)
        /// If fPreserveRootFolder is true, the first (root) folder will also be preserved
        /// Return false if the function could not remove all folders, true otherwise.
        /// </summary>
        public static bool DeleteFolder(DirectoryInfo dirInfo, bool fPreserveGit, bool fPreserveRootFolder)
        {
            bool f = true;

            try
            {
                foreach (var subDir in dirInfo.GetDirectories())
                {
                    if (fPreserveGit == false || !subDir.Name.EndsWith(".git"))
                    {
                        f &= DeleteFolder(subDir, false, false);
                    }
                }

                foreach (var file in dirInfo.GetFiles())
                {
                    f &= DeleteFile(file.FullName);
                }

                if (fPreserveRootFolder == false)
                {
                    f &= DeleteFolder(dirInfo);
                }
            }
            catch (Exception ex)
            {
                App.PrintLogMessage("Error deleting directory " + dirInfo.FullName + ": " + ex.Message, MessageType.Error);
            }
            return(f);
        }
Example #6
0
        /// <summary>
        /// Callback that handles process printing to stderr
        /// Collect all strings into one stderr variable and call a custom handler.
        /// </summary>
        private void PErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (String.IsNullOrEmpty(e.Data))   // If the stream ended
            {
                // Sometimes we receive multiple null strings on error stream
                // (example: when adding a new key with plink)
                // This catches these cases which would increment semaphore over it's limit
                try
                {
                    Exited.Release();           // release its semaphore
                }
                catch (Exception ex)
                {
                    App.PrintLogMessage(ex.Message, MessageType.Error);
                }
            }
            else
            {
                if (Result.stderr != string.Empty)
                {
                    Result.stderr += Environment.NewLine;
                }
                Result.stderr += e.Data;

                if (FStderr != null)
                {
                    App.MainForm.BeginInvoke((MethodInvoker)(() => FStderr(e.Data)));
                }
            }
        }
Example #7
0
 /// <summary>
 /// Saves the current set of repositories to a file.
 /// Returns true if save succeeded.
 /// </summary>
 public bool Save(string fileName)
 {
     try
     {
         using (FileStream file = new FileStream(fileName, FileMode.Create))
         {
             try
             {
                 BinaryFormatter wr = new BinaryFormatter();
                 wr.Serialize(file, Repos);
                 wr.Serialize(file, Default == null ? "" : Default.Path);
                 return(true);
             }
             catch (Exception ex)
             {
                 throw new ClassException(ex.Message);
             }
         }
     }
     catch (Exception ex)
     {
         App.PrintLogMessage(ex.Message, MessageType.Error);
     }
     return(false);
 }
Example #8
0
        /// <summary>
        /// Recursively create a list of directories and files from the given path.
        /// </summary>
        public static List <string> GetFilesRecursive(string path)
        {
            List <string>  result = new List <string>();
            Stack <string> stack  = new Stack <string>();

            stack.Push(path);

            while (stack.Count > 0)
            {
                string dir = stack.Pop();
                try
                {
                    result.AddRange(Directory.GetFiles(dir, "*.*"));

                    foreach (string d in
                             Directory.GetDirectories(dir).Where(d => !d.EndsWith(Path.DirectorySeparatorChar + ".git") ||
                                                                 Properties.Settings.Default.ShowDotGitFolders))
                    {
                        stack.Push(d);
                    }
                }
                catch (Exception ex)
                {
                    App.PrintLogMessage(ex.Message, MessageType.Error);
                }
            }
            return(result);
        }
Example #9
0
        /// <summary>
        /// Print into the status pane (and the aux log window).
        /// It is ok to send null or empty string.
        /// Strings that contain Newline will be broken into separate lines.
        /// This function is thread-safe.
        /// </summary>
        private void PrintStatus(string message, MessageType type)
        {
            if (string.IsNullOrEmpty(message))
            {
                return;
            }
            if (listStatus.InvokeRequired)
            {
                listStatus.BeginInvoke((MethodInvoker)(() => PrintStatus(message, type)));
            }
            else
            {
                // Add each line of the message individually
                // For performance reasons, only up to 250 characters of text are added in one call.
                foreach (string line in message.Split(new[] { Environment.NewLine }, StringSplitOptions.None))
                {
                    // Prepend the current time, if that option is requested, in either 12 or 24-hr format
                    string stamp = Properties.Settings.Default.logTime
                                   ? DateTime.Now.ToString(Properties.Settings.Default.logTime24
                                   ? "HH:mm:ss"
                                   : "hh:mm:ss") + " "
                                   : "";
                    int len = Math.Min(line.Length, 250);
                    listStatus.Items.Add(new StatusListBoxItem(stamp + line.Substring(0, len), type));
                }
                listStatus.TopIndex = listStatus.Items.Count - 1;

                App.PrintLogMessage(message, type);
            }
        }
Example #10
0
        public ExecResult Run(string args, bool async)
        {
            ExecResult output = new ExecResult();

            try
            {
                Directory.SetCurrentDirectory(Root);

                // Set the HTTPS password
                string password = Remotes.GetPassword("");
                ClassUtils.AddEnvar("PASSWORD", password);

                // The Windows limit to the command line argument length is about 8K
                // We may hit that limit when doing operations on a large number of files.
                //
                // However, when sending a long list of files, git was hanging unless
                // the total length was much less than that, so I set it to about 2000 chars
                // which seemed to work fine.

                if (args.Length < 2000)
                {
                    return(ClassGit.Run(args, async));
                }

                // Partition the args into "[command] -- [set of file chunks < 2000 chars]"
                // Basically we have to rebuild the command into multiple instances with
                // same command but with file lists not larger than about 2K
                int    i   = args.IndexOf(" -- ") + 3;
                string cmd = args.Substring(0, i + 1);
                args = args.Substring(i);       // We separate git command up to and until the list of files

                App.PrintLogMessage("Processing large amount of files: please wait...", MessageType.General);

                // Add files individually up to the length limit using the starting " file delimiter
                string[] files = args.Split(new [] { " \"" }, StringSplitOptions.RemoveEmptyEntries);
                // Note: files in the list are now stripped from their initial " character!
                i = 0;
                do
                {
                    StringBuilder batch = new StringBuilder(2100);
                    while (batch.Length < 2000 && i < files.Length)
                    {
                        batch.Append("\"" + files[i++] + " ");
                    }

                    output = ClassGit.Run(cmd + batch, async);
                    if (output.Success() == false)
                    {
                        break;
                    }
                } while (i < files.Length);
            }
            catch (Exception ex)
            {
                App.PrintLogMessage(ex.Message, MessageType.Error);
            }

            return(output);
        }
Example #11
0
        /// <summary>
        /// Callback that handles process printing to stderr.
        /// Prints the stderr to a log window.
        /// </summary>
        private void PStderr(String message)
        {
            // Remove CSI [ or ESC [ + single character sequence
            if (message.StartsWith("\u001b["))
            {
                message = message.Remove(0, 3);
            }

            // This is a workaround for Linux Mono:
            // On Windows, when we clone a remote repo, we receive each status line as a separate message
            // On Linux, it is all clumped together without any newlines (or 0A), so we inject them
            if (ClassUtils.IsMono())
            {
                // A bit of a hack since we simply hard-code recognized types of messages. Oh, well...
                message = message.Replace("remote:", Environment.NewLine + "remote:");
                message = message.Replace("Receiving", Environment.NewLine + "Receiving");
                message = message.Replace("Resolving", Environment.NewLine + "Resolving");
            }
            textStdout.AppendText(ClassUtils.ToPlainAscii(message) + Environment.NewLine, Color.Red);

            // Keep the newly added text visible
            textStdout.SelectionStart = textStdout.TextLength;
            textStdout.ScrollToCaret();

            // This hack recognizes a common problem where the host RSA key was not added to the list
            // of known hosts. Help the user by telling him that and (on Windows) offering to open the
            // Manage Keys dialog.
            if (message.Contains("key fingerprint is"))
            {
                // On Linux / Mono, we don't have a Manage SSH dialog
                if (ClassUtils.IsMono())
                {
                    MessageBox.Show(@"The remote server RSA key was not added to the list of known hosts.", @"Host Key error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                else
                {
                    DialogResult response = MessageBox.Show(@"The remote server RSA key was not added to the list of known hosts." + Environment.NewLine +
                                                            @"Would you like to open the Manage SSH Keys dialog to add the host in the Remote Keys tab?", @"Host Key error",
                                                            MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                    if (response == DialogResult.Yes)
                    {
                        FormSSH formSsh = new FormSSH();
                        formSsh.ShowDialog();
                    }
                }
            }

            // This hack recognizes a common HTTPS authentication error message
            if (message.Contains(@"fatal: Authentication failed for 'https:"))
            {
                MessageBox.Show(@"The remote server refused to authenticate you." + Environment.NewLine +
                                @"You need to set your full HTTPS credentials (user name and password) to access this repo.",
                                @"HTTPS Authentication error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }

            // Append the stderr stream message to a log window
            App.PrintLogMessage("stderr: " + message, MessageType.Error);
        }
Example #12
0
        /// <summary>
        /// Checks the path to git and checks that the git executable is functional. This call
        /// should be made only once upon the program start.
        /// It returns true if git executable can be run, false otherwise.
        /// </summary>
        public bool Initialize()
        {
            bool retValue = true;

            // Check that we have a functional version of git at an already set path
            gitPath = Properties.Settings.Default.GitPath;
            if (Exec.Run(gitPath, "--version").stdout.Contains("git version") == false)
            {
                // If we are running on Linux, get the git path by 'which' command
                if (ClassUtils.IsMono())
                {
                    gitPath = Exec.Run("which", "git").stdout.Trim();
                    if (Exec.Run(gitPath, "--version").stdout.Contains("git version") == false)
                    {
                        MessageBox.Show(
                            "Could not locate 'git'!\n\nPlease install git by running 'sudo apt-get install git'\nMake sure it is on your path, then rerun this application.",
                            "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        retValue = false;
                    }
                }
                else
                {
                    // Check if a version of git is installed at a known location (or guess a location)
                    string programFilesPath = Environment.GetEnvironmentVariable("PROGRAMFILES(X86)") ??
                                              Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
                    // If a git executable does not exist at the default location, try the 64-bit program file folder instead
                    if (!File.Exists(programFilesPath) && programFilesPath.Contains(" (x86)"))
                    {
                        programFilesPath = programFilesPath.Replace(" (x86)", "");
                    }

                    gitPath = Path.Combine(programFilesPath, @"Git\bin\git.exe");
                    if (Exec.Run(gitPath, "--version").stdout.Contains("git version") == false)
                    {
                        // Ask user to show us where the git is installed
                        FormPathToGit formPath = new FormPathToGit(programFilesPath, gitPath);
                        while (retValue = (formPath.ShowDialog() == DialogResult.OK))
                        {
                            gitPath = formPath.PathToGit;
                            if (Exec.Run(gitPath, "--version").stdout.Contains("git version"))
                            {
                                break;
                            }
                        }
                    }
                }
            }
            if (retValue)
            {
                // Run the version again to get the version code (for simplicity did not save it earlier)
                string version = string.Format("Using {0} at {1}", Exec.Run(gitPath, "--version"), gitPath);
                App.PrintLogMessage(version, MessageType.General);
                Properties.Settings.Default.GitPath = gitPath;
            }
            return(retValue);
        }
Example #13
0
        /// <summary>
        /// Constructor class function, create batch file helper in the temp space
        /// </summary>
        public ClassSSH()
        {
            string pathHelpertLong = ClassUtils.WriteResourceToFile(Path.GetTempPath(), "git_ssh_helper.sh", Properties.Resources.git_ssh_helper);

            pathHelper = ClassUtils.GetShortPathName(pathHelpertLong);
            // Make the batch file executable: this trick will only work with Mono
            File.SetAttributes(pathHelper, (FileAttributes)((uint)File.GetAttributes(pathHelper) | 0x80000000));
            App.PrintLogMessage("SSH helper path:" + pathHelper, MessageType.Error);
            ClassUtils.AddEnvar("GIT_SSH", pathHelper);
        }
Example #14
0
        /// <summary>
        /// Sets or removes a local git configuration value.
        /// If the value is null or empty string, the key will be removed (unset).
        /// </summary>
        public static void SetLocal(ClassRepo repo, string key, string value)
        {
            string setkey = string.IsNullOrEmpty(value) ? "--unset " : "";
            string val    = string.IsNullOrEmpty(value) ? "" : " \"" + value + "\"";
            string cmd    = setkey + key + val;

            if (repo.Run("config --local " + cmd).Success() == false)
            {
                App.PrintLogMessage("Error setting local git config parameter!", MessageType.Error);
            }
        }
Example #15
0
 /// <summary>
 /// Open a file browser/Explorer at the specific directory, optionally selecting a file
 /// </summary>
 public static void ExplorerHere(string where, string selFile)
 {
     try
     {
         App.PrintStatusMessage("Opening a file browser at " + where, MessageType.General);
         if (IsMono())
         {
             // Opening an "Explorer" is platform-specific and depends on the desktop environment which you use,
             // each desktop environment comes with its own default file- manager.
             //   Ubuntu: nautilus
             //   Cinnamon: nemo
             //   Mate: caja
             //   xfce: thunar
             //   KDE: dolphin
             if (File.Exists(@"/usr/bin/nautilus"))
             {
                 Process.Start(@"/usr/bin/nautilus", "--browser " + where);
             }
             else if (File.Exists(@"/usr/bin/nemo"))
             {
                 Process.Start(@"/usr/bin/nemo", where);
             }
             else if (File.Exists(@"/usr/bin/caja"))
             {
                 Process.Start(@"/usr/bin/caja", where);
             }
             else if (File.Exists(@"/usr/bin/thunar"))
             {
                 Process.Start(@"/usr/bin/thunar", where);
             }
             else if (File.Exists(@"/usr/bin/dolphin"))
             {
                 Process.Start(@"/usr/bin/dolphin", where);
             }
             else
             {
                 throw new Exception("Unable to identify a file browser program for this distro. Please report this issue - thank you!");
             }
         }
         else
         {
             string path = selFile == string.Empty
                               ? "/e,\"" + where + "\""
                               : "/e, /select,\"" + selFile + "\"";
             App.PrintLogMessage(path, MessageType.Command);
             Process.Start("explorer.exe", path);
         }
     }
     catch (Exception ex)
     {
         App.PrintLogMessage(ex.Message, MessageType.Error);
         MessageBox.Show(ex.Message, "Explorer Here error", MessageBoxButtons.OK, MessageBoxIcon.Error);
     }
 }
Example #16
0
        /// <summary>
        /// Returns a value of a local git configuration key
        /// </summary>
        public static string GetLocal(ClassRepo repo, string key)
        {
            ExecResult result = repo.Run("config --local --get " + key);

            if (result.Success())
            {
                return(result.stdout);
            }

            App.PrintLogMessage("Error getting local git config parameter!", MessageType.Error);
            return(string.Empty);
        }
Example #17
0
        /// <summary>
        /// Returns a value of a global git configuration key
        /// </summary>
        public static string GetGlobal(string key)
        {
            ExecResult result = ClassGit.Run("config --global --get " + key);

            if (result.Success())
            {
                return(result.stdout);
            }

            App.PrintLogMessage("Error getting global git config parameter!", MessageType.Error);
            return(String.Empty);
        }
Example #18
0
        /// <summary>
        /// Initializes SSH connection by running the PLINK using the specified
        /// connection parameters. This function blocks until the PLINK returns.
        /// </summary>
        public void ImportRemoteSshKey(ClassUrl.Url url)
        {
            // Build the arguments to the PLINK process: port number, user and the host
            // Use the default SSH values if the url did not provide them
            string args = " -P " + (url.Port > 0 ? url.Port.ToString() : "22") +
                          " -l " + (string.IsNullOrEmpty(url.User) ? "anonymous" : url.User) +
                          " " + url.Host;

            // plink does everything through its stderr stream
            ExecResult result = Exec.Run(pathPlink, args);

            App.PrintLogMessage(result.stderr, MessageType.Error);
        }
Example #19
0
 /// <summary>
 /// Terminate this job
 /// </summary>
 public void Terminate()
 {
     try
     {
         FStdout   = null; // Disable all callbacks since the client class could have been disposed of
         FStderr   = null;
         FComplete = null;
         Proc.Kill();    // Immediately stop the process!
     }
     catch (Exception)
     {
         App.PrintLogMessage("Exec.Terminate() exception", MessageType.Error);
     }
 }
Example #20
0
 /// <summary>
 /// Deletes a folder from the local file system.
 /// Returns true if delete succeeded, false otherwise.
 /// </summary>
 private static bool DeleteFolder(DirectoryInfo dirInfo)
 {
     try
     {
         dirInfo.Attributes = FileAttributes.Normal;
         dirInfo.Delete();
     }
     catch (Exception ex)
     {
         App.PrintLogMessage("Error deleting directory " + dirInfo.FullName + ": " + ex.Message, MessageType.Error);
         return(false);
     }
     return(true);
 }
Example #21
0
        /// <summary>
        /// Writes binary resource to a temporary file
        /// </summary>
        public static string WriteResourceToFile(string pathName, string fileName, byte[] buffer)
        {
            string path = Path.Combine(pathName, fileName);

            try
            {
                using (var sw = new BinaryWriter(File.Open(path, FileMode.Create)))
                {
                    sw.Write(buffer);
                }
            }
            catch (Exception ex)
            {
                App.PrintLogMessage(ex.Message, MessageType.Error);
            }
            return(path);
        }
Example #22
0
 /// <summary>
 /// Deletes a file from the local file system.
 /// Returns true if delete succeeded, false otherwise.
 /// </summary>
 public static bool DeleteFile(string name)
 {
     try
     {
         FileInfo file = new FileInfo(name)
         {
             Attributes = FileAttributes.Normal
         };
         file.Delete();
     }
     catch (Exception ex)
     {
         App.PrintLogMessage("Error deleting file " + name + ": " + ex.Message, MessageType.Error);
         return(false);
     }
     return(true);
 }
Example #23
0
        /// <summary>
        /// Run plink program with the given arguments
        /// </summary>
        public void RunPLink(string args)
        {
            // Start a console process
            Process proc = new Process();

            proc.StartInfo.FileName        = ClassUtils.GetShellExecCmd();
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow  = false;

            // We need to keep the CMD/SHELL window open, so start the process using
            // the CMD/SHELL as the root process and pass it our command to execute
            proc.StartInfo.Arguments = string.Format("{0} \"{1}\" {2}",
                                                     ClassUtils.GetShellExecFlags(), pathPlink, args);

            App.PrintLogMessage(proc.StartInfo.Arguments, MessageType.Command);

            proc.Start();
        }
Example #24
0
 /// <summary>
 /// The user selected an item from the list of help items to insert into
 /// the edit field.
 /// </summary>
 private void ComboHelpSelectedIndexChanged(object sender, EventArgs e)
 {
     try
     {
         // Insert (or substitute if there is a selection) first few characters
         // of a token into the corresponding edit field (kept in Tag of a combo box)
         ComboBox box = sender as ComboBox;
         box.Text = string.Empty;
         TextBox textBox = box.Tag as TextBox;
         string  token   = (string)box.SelectedItem;
         textBox.SelectedText = token.Substring(0, 2);
         textBox.Focus();
     }
     catch (Exception ex)
     {
         App.PrintLogMessage("Error: " + ex.Message, MessageType.Error);
     }
 }
Example #25
0
        /// <summary>
        /// If user checked a preference to scan for TABS, and the file extension matches,
        /// check the file(s) for TABs and EOL's spaces
        /// </summary>
        public static void CheckForTabs(List <string> files)
        {
            // Only check if the user setting enables the functionality
            if (!Properties.Settings.Default.WarnOnTabs)
            {
                return;
            }

            // Contains the final list of files that have TABs or EOL spaces
            List <string> xfiles;

            // Wrap the file checks with a performance diagnostics so we can track how long it takes to parse all files
            Stopwatch timer = new Stopwatch();

            timer.Start();
            {
                // Create a Regex expression corresponding to each type of file extension to match
                string       values  = Properties.Settings.Default.WarnOnTabsExt;
                string[]     extList = values.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                List <Regex> regexes = new List <Regex>();
                foreach (string sFileMask in extList)
                {
                    string expression = sFileMask.Trim().Replace(".", "[.]").Replace("*", ".*").Replace("?", ".") + "$";
                    regexes.Add(new Regex(expression));
                }

                xfiles = CheckTabsInFiles(files, regexes);
            }
            timer.Stop();
            App.PrintLogMessage("TabCheck: elapsed: " + timer.ElapsedMilliseconds + " ms", MessageType.Debug);

            // Print all files that have TABs or EOL spaces
            if (xfiles.Count > 0)
            {
                // Although it is a warning, internally we use a message type "Error" so the output will print in
                // red color and grab the attention
                App.PrintStatusMessage("WARNING: The following files contain TABs or EOL spaces:", MessageType.Error);
                foreach (string xfile in xfiles)
                {
                    App.PrintStatusMessage(xfile, MessageType.Error);
                }
            }
        }
Example #26
0
        /// <summary>
        /// Main command execution function.
        /// Upon completion, prints all errors to the log window.
        /// </summary>
        public static ExecResult Run(string cmd, string args)
        {
            App.PrintLogMessage(String.Format("Exec: {0} {1}", cmd, args), MessageType.Command);
            App.StatusBusy(true);
            Exec job = new Exec(cmd, args);

            job.Thread = new Thread(job.ThreadedRun);
            job.Thread.Start(10000);
            job.Thread.Join();
            // There are known problems with async output not being flushed as the
            // thread exits. Releasing a time-slice using DoEvents seems to fix
            // the problem in this particular setting.
            Application.DoEvents();
            App.StatusBusy(false);
            if (job.Result.Success() == false)
            {
                App.PrintLogMessage("Error: " + job.Result.stderr, MessageType.Error);
            }

            return(job.Result);
        }
Example #27
0
        /// <summary>
        /// Check a list of files, filtered by a list of Regex expressions, for TABs or EOL spaces
        /// Returns a subset of files that contain TABs or EOL spaces
        /// </summary>
        private static List <string> CheckTabsInFiles(List <string> files, List <Regex> regexes)
        {
            List <string> xfiles = new List <string>();

            // Filter which files to check by using a regular expression of each file name
            foreach (string file in files)
            {
                foreach (Regex regex in regexes)
                {
                    // This file is to be checked using this particular regular expression
                    if (regex.IsMatch(file))
                    {
                        App.PrintLogMessage("TabCheck: " + file, MessageType.Debug);
                        if (CheckTabsInFile(file))
                        {
                            xfiles.Add(file);
                        }
                    }
                }
            }
            return(xfiles);
        }
Example #28
0
 /// <summary>
 /// Edit selected file using either the default editor (native OS file association,
 /// if the tag is null, or the editor program specified in the tag field.
 /// This is a handler for the context menu, edit tool bar button and also
 /// revision history view menus.
 /// </summary>
 public static void FileOpenFromMenu(object sender, string file)
 {
     try
     {
         if (sender is ToolStripMenuItem)
         {
             object opt = (sender as ToolStripMenuItem).Tag;
             if (opt != null)
             {
                 App.PrintLogMessage("Exec: " + opt.ToString() + " " + file, MessageType.General);
                 Process.Start(opt.ToString(), file);
                 return;
             }
         }
         App.PrintLogMessage("Exec: " + file, MessageType.General);
         Process.Start(file);
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
     }
 }
Example #29
0
        /// <summary>
        /// Load or merge a set of repositories from a file.
        /// Returns true is loading succeeded and this class is assigned a new set of repos.
        /// Returns false if loading failed, or was cancelled. The repos in this class did not change.
        /// If the requested operation is a merge, isImport=true, the new set of repos will be merged with the existing one.
        /// </summary>
        public bool Load(string fileName, bool isImport)
        {
            // Wrap the opening of a repository database with an outer handler
            try
            {
                using (FileStream file = new FileStream(fileName, FileMode.Open))
                {
                    try
                    {
                        // Load list of repos and the default repo string into temporary objects
                        BinaryFormatter  rd          = new BinaryFormatter();
                        List <ClassRepo> newRepos    = (List <ClassRepo>)rd.Deserialize(file);
                        string           defaultRepo = (string)rd.Deserialize(file);

                        // WAR: Mono 2.6.7 does not support serialization of a HashSet. At the same time...
                        // Quickly check that each repo is valid (find if at least one is not)
                        bool allOK = true;
                        foreach (ClassRepo repo in newRepos)
                        {
                            allOK &= ClassUtils.DirStat(repo.Path) == ClassUtils.DirStatType.Git;
                            repo.ExpansionReset(null);
                        }

                        // If at least one repo was not valid, give the user a chance to recreate it
                        if (allOK == false)
                        {
                            FormRecreateRepos recreateRepos = new FormRecreateRepos();
                            recreateRepos.Repos = newRepos;
                            // The "Accept" button in the recreate repos dialog will not be enabled
                            // until every repo has been configured properly. User can always cancel
                            // that process in which case we will not load the selected repo.
                            if (recreateRepos.ShowDialog() == DialogResult.Cancel)
                            {
                                return(false);
                            }
                            newRepos = recreateRepos.Repos;
                        }

                        // If the operation is a simple load, assign our object's list of repos
                        // Otherwise, we merge the new set with the existing one
                        if (isImport)
                        {
                            Repos.AddRange(newRepos);
                        }
                        // After we merge the new set of repos, current/default repo remains the same
                        else
                        {
                            Repos = newRepos;
                            // Upon load, set the current based on the default repo
                            Default = Repos.Find(r => r.Path == defaultRepo);
                            SetCurrent(Default);
                        }
                        return(true);
                    }
                    catch (Exception ex)
                    {
                        throw new ClassException(ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                App.PrintLogMessage(ex.Message, MessageType.Error);
            }
            return(false);
        }
Example #30
0
        /// <summary>
        /// Runs a custom tool.
        /// Returns a string with a tool output to be printed out.
        /// This string can be empty, in which case nothing should be printed.
        /// </summary>
        public string Run(List <string> files)
        {
            App.PrintLogMessage(ToString(), MessageType.Command);

            string stdout = string.Empty;
            string args   = DeMacroise(Args, files);

            // Add custom arguments if the checkbox to Prompt for Arguments was checked
            if (IsPromptForArgs)
            {
                // Description is used as a question for the arguments, shown in the window title bar
                string desc = Name;
                if (!string.IsNullOrEmpty(Desc))
                {
                    desc += ": " + Desc;
                }

                FormCustomToolArgs formCustomToolArgs = new FormCustomToolArgs(desc, args, IsAddBrowse);
                if (formCustomToolArgs.ShowDialog() == DialogResult.Cancel)
                {
                    return(string.Empty);
                }

                args = formCustomToolArgs.GetArgs();
            }

            App.StatusBusy(true);

            // Prepare the process to be run
            Process proc = new Process();

            proc.StartInfo.FileName         = "\"" + Cmd + "\"";
            proc.StartInfo.Arguments        = args;
            proc.StartInfo.WorkingDirectory = DeMacroise(Dir, new List <string>());
            proc.StartInfo.UseShellExecute  = false;

            try
            {
                // Run the custom tool in two ways (console app and GUI app)
                if (IsConsoleApp)
                {
                    // Start a console process
                    proc.StartInfo.CreateNoWindow = false;

                    // If we have to keep the window open (CMD/SHELL) after exit,
                    // we start the command line app in a different way, using a
                    // shell command (in which case we cannot redirect the stdout)
                    if (IsCloseWindowOnExit)
                    {
                        App.MainForm.SetTitle("Waiting for " + Cmd + " to finish...");

                        // Redirect standard output to our status pane if requested
                        if (IsWriteOutput)
                        {
                            proc.StartInfo.RedirectStandardOutput = true;
                            proc.StartInfo.RedirectStandardError  = true;
                            proc.OutputDataReceived += ProcOutputDataReceived;
                            proc.ErrorDataReceived  += ProcErrorDataReceived;
                            proc.Start();
                            proc.BeginOutputReadLine();
                            proc.WaitForExit();
                        }
                        else
                        {
                            proc.Start();
                            proc.WaitForExit();
                        }
                    }
                    else
                    {
                        // We need to keep the CMD/SHELL window open, so start the process using
                        // the CMD/SHELL as the root process and pass it our command to execute
                        proc.StartInfo.Arguments = string.Format("{0} {1} {2}",
                                                                 ClassUtils.GetShellExecFlags(), proc.StartInfo.FileName, proc.StartInfo.Arguments);
                        proc.StartInfo.FileName = ClassUtils.GetShellExecCmd();
                        App.PrintLogMessage(proc.StartInfo.Arguments, MessageType.Command);

                        proc.Start();
                    }
                }
                else
                {
                    // Start a GUI process
                    proc.StartInfo.CreateNoWindow = true;

                    // We can start the process and wait for it to finish only if we need to
                    // refresh the app after the process has exited.
                    proc.Start();
                }

                if (IsRefresh)
                {
                    App.MainForm.SetTitle("Waiting for " + Cmd + " to finish...");

                    proc.WaitForExit();

                    App.DoRefresh();
                }
            }
            catch (Exception ex)
            {
                App.PrintStatusMessage(ex.Message, MessageType.Error);
                MessageBox.Show(ex.Message, "Error executing custom tool", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            proc.Close();
            App.StatusBusy(false);

            return(stdout);
        }