Frage

Wir haben VisualSVN Server einrichten, wie unser Subversion-Server unter Windows, und wir verwenden AnkhSVN + TortoiseSVN als Kunden auf unseren Workstations.

Wie können Sie den Server so konfigurieren, dass erfordern Nachrichten begehen als nicht leer?

War es hilfreich?

Lösung

VisualSVN Server 3.9 bietet die VisualSVNServerHooks.exe check-logmessage Haken pre-commit, die Sie Nachrichten ablehnen begeht mit leeren oder Kurzprotokoll hilft. Siehe den Artikel KB140. Validieren von Log-Meldungen in VisualSVN Server Anweisungen commit

Neben dem eingebauten in VisualSVNServerHooks.exe, VisualSVN Server und SVN im allgemeinen verwendet eine Nummer rel="nofollow Haken Aufgaben wie dies zu erreichen.

  • start-commit - laufen, bevor Commit-Transaktion beginnt, kann verwendet werden, um spezielle Erlaubnis zu tun Überprüfung
  • pre-commit - am Ende des Laufes Transaktion, aber bevor begehen. Häufig verwendete Dinge zu überprüfen, wie eine nicht Null Länge Protokollmeldung.
  • post-commit - läuft nach der Transaktion wurde engagiert sein. Kann für das Senden von E-Mails verwendet werden, oder das Sichern Repository.
  • pre-revprop-change - läuft vor einer Revision Eigenschaftsänderung. Kann verwendet werden, Berechtigungen zu überprüfen.
  • post-revprop-change - läuft nach einer Revision Eigenschaftsänderung. Können diese Änderungen per E-Mail oder Backup verwendet werden.

Sie müssen den pre-commit Haken verwenden. Sie können es sich in fast jeder Sprache schreiben Sie Ihre Plattform unterstützt, aber es gibt eine Reihe von Skripten auf dem Netz. Googeln „svn precommit Haken verlangen Kommentar“ fand ich ein paar, die aussahen, als wären sie die Rechnung passen würde:

Andere Tipps

Ich bin froh, dass Sie diese Frage gestellt. Dies ist unser Hook-Skript pre-commit geschrieben gemeinsam Windows-Batch . Es leugnet begehen, wenn die Log-Nachricht weniger als 6 Zeichen ist. Legen Sie einfach die Pre-commit.bat Ihren Haken Verzeichnis.

Pre-commit.bat

setlocal enabledelayedexpansion

set REPOS=%1
set TXN=%2

set SVNLOOK="%VISUALSVN_SERVER%\bin\svnlook.exe"

SET M=

REM Concatenate all the lines in the commit message
FOR /F "usebackq delims==" %%g IN (`%SVNLOOK% log -t %TXN% %REPOS%`) DO SET M=!M!%%g

REM Make sure M is defined
SET M=0%M%

REM Here the 6 is the length we require
IF NOT "%M:~6,1%"=="" goto NORMAL_EXIT

:ERROR_TOO_SHORT
echo "Commit note must be at least 6 letters" >&2
goto ERROR_EXIT

:ERROR_EXIT
exit /b 1

REM All checks passed, so allow the commit.
:NORMAL_EXIT
exit 0

Die technischen Antworten auf Ihre Frage bereits gegeben worden. Ich mag die soziale Antwort hinzuzufügen, das lautet: „Durch die Nachrichtenstandards mit Ihrem Team Gründung begehen und bekommen sie zustimmen (oder zu akzeptieren) Gründe, warum man braucht ausdruck Nachrichten begehen“

Ich habe so viele gesehen begehen Nachrichten, die „Patch“ sagte: „Tippfehler“, „fix“ oder ähnlich, dass ich nicht verzählt habe.

Wirklich - machen es jedem klar, warum Sie sie brauchen würde

.

Beispiele für Gründe hierfür sind:

  • Erzeugt Changenotes (gut - this'd eigentlich ein schönes automatisches Werkzeug macht gute Nachrichten zu erzwingen, wenn ich weiß, dass sie (mit meinem Namen sein werden) öffentlich sichtbar - wenn auch nur für das Team)
  • Lizenzfragen : Sie müssen möglicherweise die Herkunft des Codes wissen später, z.B. sollten Sie die Lizenz, um Ihren Code zu ändern (Einige Organisationen auch Standards für Commitnachricht Formatierung - na ja, können Sie die Überprüfung für diese automatisieren könnte, aber Sie würden nicht unbedingt bekommen gut Commit-Nachrichten mit diesem )
  • Die Interoperabilität mit anderen Werkzeugen , z.B. bugtrackers / Ausgabe-Management-Systeme, die eine Schnittstelle mit Versionskontrolle und Extraktion von Informationen aus den Commit-Nachrichten.

Hope, die zusätzlich zu den technischen Antworten zu precommit Haken helfen.

Hier ist eine zweiteilige Probe Batch + Powershell pre-commit Haken, der eine Log-Nachricht mit weniger als 25 Zeichen verweigert begehen.

Setzen Sie beide pre-commit.bat und pre-commit.ps1 in Ihr Repository hooks Ordner, z.B. C:\Repositories\repository\hooks\

Pre-commit.ps1

# Store hook arguments into variables with mnemonic names
$repos    = $args[0]
$txn      = $args[1]

# Build path to svnlook.exe
$svnlook = "$env:VISUALSVN_SERVER\bin\svnlook.exe"

# Get the commit log message
$log = (&"$svnlook" log -t $txn $repos)

# Check the log message contains non-empty string
$datalines = ($log | where {$_.trim() -ne ""})
if ($datalines.length -lt 25)
{
  # Log message is empty. Show the error.
  [Console]::Error.WriteLine("Commit with empty log message is prohibited.")
  exit 3
}

exit 0

Pre-commit.bat

@echo off
set PWSH=%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe
%PWSH% -command $input ^| %1\hooks\pre-commit.ps1 %1 %2
if errorlevel 1 exit %errorlevel%

Anmerkung 1:. pre-commit.bat ist die einzige, die von VisualSVN aufgerufen werden kann und dann pre-commit.ps1 ist derjenige, der durch pre-commit.bat genannt wird

Hinweis 2:. pre-commit.bat auch genannt pre-commit.cmd werden

Hinweis. 3: Wenn Sie mit einigen akzentuierte Zeichen kodieren Themen experimentieren und die [Console]::Error.WriteLine Ausgabe, fügen Sie dann zum Beispiel chcp 1252 in pre-commit.bat, nächste Zeile nach @echo off

Was VisualSVN bietet Ihnen eingeben, wie Haken „Windows NT-Befehlsscripts“ sind, die im Grunde Batch-Dateien sind.

Schreiben if-then-else in Batch-Dateien sind sehr hässlich und wahrscheinlich sehr schwer zu debuggen.

Es wird in etwa wie folgt (für Pre-commit.bat Suche) suchen (nicht getestet):

SVNLOOK.exe log -t "%2" "%1" | grep.exe "[a-zA-Z0-9]" > nul || GOTO ERROR
GOTO OK
:ERROR
ECHO "Please enter comment and then retry commit!"
exit 1
:OK
exit 0 

Sie benötigen einen grep.exe auf dem Weg,% 1 ist der Pfad zu diesem Repository% 2 der Name des TXN begangen werden soll. Haben Sie auch einen Blick auf die vorge commit.tmpl im Haken-Verzeichnis Ihres Repository.

Wir nutzen die hervorragende CS-Script Werkzeug für unsere Haken pre-commit, damit wir Skripte schreiben können in die Sprache, die wir dabei Entwicklung sind. Hier ist ein Beispiel, das eine es Commitnachricht länger als 10 Zeichen gewährleistet und stellt sicher, dass .suo und .user Dateien werden nicht eingecheckt. Sie können auch für Reiter / Raum Einzüge testen wollen, oder kleine Code-Standards Durchsetzung beim Check-in, aber vorsichtig sein, macht das Skript tun zu viel, wie Sie wollen nicht verlangsamen ein begehen.

// run from pre-commit.cmd like so:
// css.exe /nl /c C:\SVN\Scripts\PreCommit.cs %1 %2
using System;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;

class PreCommitCS {

  /// <summary>Controls the procedure flow of this script</summary>
  public static int Main(string[] args) {
    if (args.Length < 2) {
      Console.WriteLine("usage: PreCommit.cs repository-path svn-transaction");
      Environment.Exit(2);
    }

    try {
      var proc = new PreCommitCS(args[0], args[1]);
      proc.RunChecks();
      if (proc.MessageBuffer.ToString().Length > 0) {
        throw new CommitException(String.Format("Pre-commit hook violation\r\n{0}", proc.MessageBuffer.ToString()));
      }
    }
    catch (CommitException ex) {
      Console.WriteLine(ex.Message);
      Console.Error.WriteLine(ex.Message);
      throw ex;
    }
    catch (Exception ex) {
      var message = String.Format("SCRIPT ERROR! : {1}{0}{2}", "\r\n", ex.Message, ex.StackTrace.ToString());
      Console.WriteLine(message);
      Console.Error.WriteLine(message);
      throw ex;
    }

    // return success if we didn't throw
    return 0;
  }

  public string RepoPath { get; set; }
  public string SvnTx { get; set; }
  public StringBuilder MessageBuffer { get; set; }

  /// <summary>Constructor</summary>
  public PreCommitCS(string repoPath, string svnTx) {
    this.RepoPath = repoPath;
    this.SvnTx = svnTx;
    this.MessageBuffer = new StringBuilder();
  }

  /// <summary>Main logic controller</summary>
  public void RunChecks() {
    CheckCommitMessageLength(10);

    // Uncomment for indent checks
    /*
    string[] changedFiles = GetCommitFiles(
      new string[] { "A", "U" },
      new string[] { "*.cs", "*.vb", "*.xml", "*.config", "*.vbhtml", "*.cshtml", "*.as?x" },
      new string[] { "*.designer.*", "*.generated.*" }
    );
    EnsureTabIndents(changedFiles);
    */

    CheckForIllegalFileCommits(new string[] {"*.suo", "*.user"});
  }

  private void CheckForIllegalFileCommits(string[] filesToExclude) {
    string[] illegalFiles = GetCommitFiles(
      new string[] { "A", "U" },
      filesToExclude,
      new string[] {}
    );
    if (illegalFiles.Length > 0) {
      Echo(String.Format("You cannot commit the following files: {0}", String.Join(",", illegalFiles)));
    }
  }

  private void EnsureTabIndents(string[] filesToCheck) {
    foreach (string fileName in filesToCheck) {
      string contents = GetFileContents(fileName);
      string[] lines = contents.Replace("\r\n", "\n").Replace("\r", "\n").Split(new string[] { "\n" }, StringSplitOptions.None);
      var linesWithSpaceIndents =
        Enumerable.Range(0, lines.Length)
             .Where(i => lines[i].StartsWith(" "))
             .Select(i => i + 1)
             .Take(11)
             .ToList();
      if (linesWithSpaceIndents.Count > 0) {
        var message = String.Format("{0} has spaces for indents on line(s): {1}", fileName, String.Join(",", linesWithSpaceIndents));
        if (linesWithSpaceIndents.Count > 10) message += "...";
        Echo(message);
      }
    }
  }

  private string GetFileContents(string fileName) {
    string args = GetSvnLookCommandArgs("cat") + " \"" + fileName + "\"";
    string svnlookResults = ExecCmd("svnlook", args);
    return svnlookResults;
  }

  private void CheckCommitMessageLength(int minLength) {
    string args = GetSvnLookCommandArgs("log");
    string svnlookResults = ExecCmd("svnlook", args);
    svnlookResults = (svnlookResults ?? "").Trim();
    if (svnlookResults.Length < minLength) {
      if (svnlookResults.Length > 0) {
        Echo("Your commit message was too short.");
      }
      Echo("Please describe the changes you've made in a commit message in order to successfully commit. Include support ticket number if relevant.");
    }
  }

  private string[] GetCommitFiles(string[] changedIds, string[] includedFiles, string[] exclusions) {
    string args = GetSvnLookCommandArgs("changed");
    string svnlookResults = ExecCmd("svnlook", args);
    string[] lines = svnlookResults.Split(new string[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
    var includedPatterns = (from a in includedFiles select ConvertWildcardPatternToRegex(a)).ToArray();
    var excludedPatterns = (from a in exclusions select ConvertWildcardPatternToRegex(a)).ToArray();
    var opts = RegexOptions.IgnoreCase;
    var results =
      from line in lines
      let fileName = line.Substring(1).Trim()
      let changeId = line.Substring(0, 1).ToUpper()
      where changedIds.Any(x => x.ToUpper() == changeId)
      && includedPatterns.Any(x => Regex.IsMatch(fileName, x, opts))
      && !excludedPatterns.Any(x => Regex.IsMatch(fileName, x, opts))
      select fileName;
    return results.ToArray();
  }

  private string GetSvnLookCommandArgs(string cmdType) {
    string args = String.Format("{0} -t {1} \"{2}\"", cmdType, this.SvnTx, this.RepoPath);
    return args;
  }

  /// <summary>
  /// Executes a command line call and returns the output from stdout.
  /// Raises an error is stderr has any output.
  /// </summary>
  private string ExecCmd(string command, string args) {
    Process proc = new Process();
    proc.StartInfo.FileName = command;
    proc.StartInfo.Arguments = args;
    proc.StartInfo.UseShellExecute = false;
    proc.StartInfo.CreateNoWindow = true;
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.RedirectStandardError = true;
    proc.Start();

    var stdOut = proc.StandardOutput.ReadToEnd();
    var stdErr = proc.StandardError.ReadToEnd();

    proc.WaitForExit(); // Do after ReadToEnd() call per: http://chrfalch.blogspot.com/2008/08/processwaitforexit-never-completes.html

    if (!string.IsNullOrWhiteSpace(stdErr)) {
      throw new Exception(string.Format("Error: {0}", stdErr));
    }

    return stdOut;
  }

  /// <summary>
  /// Writes the string provided to the Message Buffer - this fails
  /// the commit and this message is presented to the comitter.
  /// </summary>
  private void Echo(object s) {
    this.MessageBuffer.AppendLine((s == null ? "" : s.ToString()));
  }

  /// <summary>
  /// Takes a wildcard pattern (like *.bat) and converts it to the equivalent RegEx pattern
  /// </summary>
  /// <param name="wildcardPattern">The wildcard pattern to convert.  Syntax similar to VB's Like operator with the addition of pipe ("|") delimited patterns.</param>
  /// <returns>A regex pattern that is equivalent to the wildcard pattern supplied</returns>
  private string ConvertWildcardPatternToRegex(string wildcardPattern) {
    if (string.IsNullOrEmpty(wildcardPattern)) return "";

    // Split on pipe
    string[] patternParts = wildcardPattern.Split('|');

    // Turn into regex pattern that will match the whole string with ^$
    StringBuilder patternBuilder = new StringBuilder();
    bool firstPass = true;
    patternBuilder.Append("^");
    foreach (string part in patternParts) {
      string rePattern = Regex.Escape(part);

      // add support for ?, #, *, [...], and [!...]
      rePattern = rePattern.Replace("\\[!", "[^");
      rePattern = rePattern.Replace("\\[", "[");
      rePattern = rePattern.Replace("\\]", "]");
      rePattern = rePattern.Replace("\\?", ".");
      rePattern = rePattern.Replace("\\*", ".*");
      rePattern = rePattern.Replace("\\#", "\\d");

      if (firstPass) {
        firstPass = false;
      }
      else {
        patternBuilder.Append("|");
      }
      patternBuilder.Append("(");
      patternBuilder.Append(rePattern);
      patternBuilder.Append(")");
    }
    patternBuilder.Append("$");

    string result = patternBuilder.ToString();
    if (!IsValidRegexPattern(result)) {
      throw new ArgumentException(string.Format("Invalid pattern: {0}", wildcardPattern));
    }
    return result;
  }

  private bool IsValidRegexPattern(string pattern) {
    bool result = true;
    try {
      new Regex(pattern);
    }
    catch {
      result = false;
    }
    return result;
  }
}

public class CommitException : Exception {
  public CommitException(string message) : base(message) {
  }
}

Hier ist ein Windows-Shell JScript, dass Sie, indem Sie den Haken wie verwenden können:

%SystemRoot%\System32\CScript.exe //nologo <..path..to..script> %1 %2

Es ist ziemlich einfach zu lesen, so gehen Sie vor einem Experiment.

BTW, der Grund, warum dies in JScript zu tun, ist, dass es nicht auf andere Tools angewiesen (Perl, CygWin, etc.) installiert werden.

if (WScript.Arguments.Length < 2)
{
    WScript.StdErr.WriteLine("Repository Hook Error: Missing parameters. Should be REPOS_PATH then TXN_NAME, e.g. %1 %2 in pre-commit hook");
    WScript.Quit(-1);
}

var oShell = new ActiveXObject("WScript.Shell");
var oFSO = new ActiveXObject("Scripting.FileSystemObject");

var preCommitStdOut = oShell.ExpandEnvironmentStrings("%TEMP%\\PRE-COMMIT." + WScript.Arguments(1) + ".stdout");
var preCommitStdErr = oShell.ExpandEnvironmentStrings("%TEMP%\\PRE-COMMIT." + WScript.Arguments(1) + ".stderr");

var commandLine = "%COMSPEC% /C \"C:\\Program Files\\VisualSVN Server\\bin\\SVNLook.exe\" log -t ";

commandLine += WScript.Arguments(1);
commandLine += " ";
commandLine += WScript.Arguments(0);
commandLine += "> " + preCommitStdOut + " 2> " + preCommitStdErr;


// Run Synchronously, don't show a window
// WScript.Echo("About to run: " + commandLine);
var exitCode = oShell.Run(commandLine, 0, true);

var fsOUT = oFSO.GetFile(preCommitStdOut).OpenAsTextStream(1);
var fsERR = oFSO.GetFile(preCommitStdErr).OpenAsTextStream(1);

var stdout = fsOUT && !fsOUT.AtEndOfStream ? fsOUT.ReadAll() : "";
var stderr = fsERR && !fsERR.AtEndOfStream ? fsERR.ReadAll() : "";

if (stderr.length > 0)
{
    WScript.StdErr.WriteLine("Error with SVNLook: " + stderr);
    WScript.Quit(-2);
}

// To catch naught commiters who write 'blah' as their commit message

if (stdout.length < 5)
{
    WScript.StdErr.WriteLine("Please provide a commit message that describes why you've made these changes.");
    WScript.Quit(-3);
}

WScript.Quit(0);

Verwenden Sie diese pre-commit Haken unter Windows. Es ist in Windows Batch geschrieben und verwendet grep Kommandozeilen-Programm, um die Commit Länge zu überprüfen.

svnlook log -t "%2" "%1" | c:\tools\grep -c "[a-zA-z0-9]" > nul
if %ERRORLEVEL% NEQ 1 exit 0

echo Please enter a check-in comment 1>&2
exit 1

Denken Sie daran, dass Sie eine Kopie von grep benötigen, empfehle ich die Gnu-Tools Version .

Hinweis: Dies gilt nur für TortoiseSVN

Einfach mit dem rechten Maustaste auf die oberste Ebene Ihres Repository. Im Kontext-Menü wählen Sie TortoiseSVN, dann auf Eigenschaften, um diesen Dialog zu sehen:

eingeben Bild Beschreibung hier

Klicken Sie auf die Schaltfläche Neu in der Nähe der unteren rechten Ecke, und wählen Sie Log Größen. Geben Sie die Anzahl der Zeichen, die Sie benötigen wollen für Commit und Sperren (10 in Beispiel unten).

eingeben Bild Beschreibung hier

Begeht ein von der obersten Ebene Verzeichnis Sie gerade geändert. Nun erfordert das Repository für alle Benutzer vor Begehen Änderungen Stellung zu nehmen.

Vor dem Haken zu meinem Server verpflichten hinzufügen, ich svnprops die TortoiseSVN Kunden nur verteilt.

So, als Alternative:

In TortoiseSVN -> Eigenschaften Eigenschaftsname -. Hinzufügen / set tsvn:logminsize entsprechend

Das ist natürlich keine Garantie auf dem Server als Kunden / Benutzer kann entscheiden, es nicht zu tun, aber Sie können svnprops Dateien verteilen, wenn Sie möchten. Auf diese Weise können Benutzer müssen nicht ihre eigenen Werte -. Sie sie allen Benutzern zur Verfügung stellen kann

Das funktioniert auch für Dinge wie bugtraq. Einstellungen Issue-Tracking-Material in den Protokollen zu verknüpfen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top