github.com/jdhenke/godel@v0.0.0-20161213181855-abeb3861bf0d/cmd/githubwiki/githubwiki_test.go (about)

     1  // Copyright 2016 Palantir Technologies, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package githubwiki
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"io/ioutil"
    21  	"os/exec"
    22  	"path"
    23  	"regexp"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/nmiyake/pkg/dirs"
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  
    31  	"github.com/palantir/godel/apps/distgo/pkg/git/gittest"
    32  )
    33  
    34  func TestSyncGitHubWiki(t *testing.T) {
    35  	tmpDir, cleanup, err := dirs.TempDir("", "")
    36  	defer cleanup()
    37  	require.NoError(t, err)
    38  
    39  	srcRepoParams := commitUserParam{
    40  		authorName:     "src-author",
    41  		authorEmail:    "src-author@email.com",
    42  		committerName:  "src-committer",
    43  		committerEmail: "src-committer@email.com",
    44  	}
    45  
    46  	for i, currCase := range []struct {
    47  		params      commitUserParam
    48  		msg         string
    49  		want        commitUserParam
    50  		wantMessage func(docsDir string) string
    51  	}{
    52  		// provided parameters are used
    53  		{
    54  			params: commitUserParam{
    55  				authorName:     "Author Name",
    56  				authorEmail:    "author@email.com",
    57  				committerName:  "Committer Name",
    58  				committerEmail: "committer@email.com",
    59  			},
    60  			want: commitUserParam{
    61  				authorName:     "Author Name",
    62  				authorEmail:    "author@email.com",
    63  				committerName:  "Committer Name",
    64  				committerEmail: "committer@email.com",
    65  			},
    66  			msg: "Unit test message",
    67  			wantMessage: func(docsDir string) string {
    68  				return "Unit test message"
    69  			},
    70  		},
    71  		// if parameters are empty, values from source commit are used
    72  		{
    73  			params: commitUserParam{},
    74  			want:   srcRepoParams,
    75  			msg:    "Unit test message",
    76  			wantMessage: func(docsDir string) string {
    77  				return "Unit test message"
    78  			},
    79  		},
    80  		// templating commit message works
    81  		{
    82  			params: commitUserParam{},
    83  			want:   srcRepoParams,
    84  			msg:    `CommitID: {{.CommitID}}, CommitTime: {{.CommitTime.Unix}}`,
    85  			wantMessage: func(docsDir string) string {
    86  				commitID := gitCommitID(t, docsDir)
    87  				commitTime := gitCommitTime(t, docsDir)
    88  				return fmt.Sprintf("CommitID: %s, CommitTime: %s", commitID, commitTime)
    89  			},
    90  		},
    91  		// invalid template message is used as string literal
    92  		{
    93  			params: commitUserParam{},
    94  			want:   srcRepoParams,
    95  			msg:    "CommitID: {{.CommitID}",
    96  			wantMessage: func(docsDir string) string {
    97  				return "CommitID: {{.CommitID}"
    98  			},
    99  		},
   100  	} {
   101  		currCaseTmpDir, err := ioutil.TempDir(tmpDir, fmt.Sprintf("case-%d-", i))
   102  		require.NoError(t, err)
   103  
   104  		// src repo
   105  		githubWikiSrcRepo, err := ioutil.TempDir(currCaseTmpDir, "github-wiki-")
   106  		require.NoError(t, err)
   107  		gittest.InitGitDir(t, githubWikiSrcRepo)
   108  
   109  		// add commit with specific user and committer
   110  		err = ioutil.WriteFile(path.Join(githubWikiSrcRepo, "foo.txt"), []byte("foo"), 0644)
   111  		require.NoError(t, err)
   112  		err = git(githubWikiSrcRepo).commitAll("Original commit message", srcRepoParams)
   113  		require.NoError(t, err)
   114  
   115  		// bare version of source repo
   116  		githubWikiBareRepo := gitCloneBare(t, githubWikiSrcRepo, currCaseTmpDir)
   117  
   118  		// docs directory
   119  		docsDir, err := ioutil.TempDir(tmpDir, "docs-")
   120  		require.NoError(t, err)
   121  		gittest.InitGitDir(t, docsDir)
   122  		err = ioutil.WriteFile(path.Join(docsDir, "page.md"), []byte("Test page"), 0644)
   123  		require.NoError(t, err)
   124  		gittest.CommitAllFiles(t, docsDir, "Initial docs directory commit")
   125  
   126  		err = SyncGitHubWiki(Params{
   127  			DocsDir:        docsDir,
   128  			Repo:           githubWikiBareRepo,
   129  			AuthorName:     currCase.params.authorName,
   130  			AuthorEmail:    currCase.params.authorEmail,
   131  			CommitterName:  currCase.params.committerName,
   132  			CommitterEmail: currCase.params.committerEmail,
   133  			Msg:            currCase.msg,
   134  		}, ioutil.Discard)
   135  		require.NoError(t, err, "Case %d", i)
   136  
   137  		got := commitUserParamForRepo(t, git(githubWikiBareRepo))
   138  		assert.Equal(t, currCase.wantMessage(docsDir), gitMessage(t, githubWikiBareRepo), "Case %d", i)
   139  		assert.Equal(t, currCase.want, got, "Case %d", i)
   140  	}
   141  }
   142  
   143  // Tests operations when documents directory being published is not in a Git repository.
   144  func TestSyncGitHubWikiNonGitDocsDir(t *testing.T) {
   145  	tmpDir, cleanup, err := dirs.TempDir("", "")
   146  	defer cleanup()
   147  	require.NoError(t, err)
   148  
   149  	srcRepoParams := commitUserParam{
   150  		authorName:     "src-author",
   151  		authorEmail:    "src-author@email.com",
   152  		committerName:  "src-committer",
   153  		committerEmail: "src-committer@email.com",
   154  	}
   155  
   156  	for i, currCase := range []struct {
   157  		params           commitUserParam
   158  		msg              string
   159  		want             commitUserParam
   160  		wantMessage      func(docsDir string) string
   161  		wantStdoutRegexp string
   162  	}{
   163  		// if input directory is not in a Git repository, templating will not work. Warning is printed to stdout, but operation still completes.
   164  		{
   165  			params: commitUserParam{},
   166  			want:   srcRepoParams,
   167  			msg:    `CommitID: {{.CommitID}}, CommitTime: {{.CommitTime.Unix}}`,
   168  			wantMessage: func(docsDir string) string {
   169  				return `CommitID: {{.CommitID}}, CommitTime: {{.CommitTime.Unix}}`
   170  			},
   171  			wantStdoutRegexp: "(?s).+Continuing with templating disabled. To fix this issue, ensure that the directory is in a Git repository.",
   172  		},
   173  	} {
   174  		currCaseTmpDir, err := ioutil.TempDir(tmpDir, fmt.Sprintf("case-%d-", i))
   175  		require.NoError(t, err)
   176  
   177  		// src repo
   178  		githubWikiSrcRepo, err := ioutil.TempDir(currCaseTmpDir, "github-wiki-")
   179  		require.NoError(t, err)
   180  		gittest.InitGitDir(t, githubWikiSrcRepo)
   181  
   182  		// add commit with specific user and committer
   183  		err = ioutil.WriteFile(path.Join(githubWikiSrcRepo, "foo.txt"), []byte("foo"), 0644)
   184  		require.NoError(t, err)
   185  		err = git(githubWikiSrcRepo).commitAll("Original commit message", srcRepoParams)
   186  		require.NoError(t, err)
   187  
   188  		// bare version of source repo
   189  		githubWikiBareRepo := gitCloneBare(t, githubWikiSrcRepo, currCaseTmpDir)
   190  
   191  		// docs directory
   192  		docsDir, err := ioutil.TempDir(tmpDir, "docs-")
   193  		require.NoError(t, err)
   194  		err = ioutil.WriteFile(path.Join(docsDir, "page.md"), []byte("Test page"), 0644)
   195  		require.NoError(t, err)
   196  
   197  		buf := &bytes.Buffer{}
   198  		err = SyncGitHubWiki(Params{
   199  			DocsDir:        docsDir,
   200  			Repo:           githubWikiBareRepo,
   201  			AuthorName:     currCase.params.authorName,
   202  			AuthorEmail:    currCase.params.authorEmail,
   203  			CommitterName:  currCase.params.committerName,
   204  			CommitterEmail: currCase.params.committerEmail,
   205  			Msg:            currCase.msg,
   206  		}, buf)
   207  		require.NoError(t, err, "Case %d", i)
   208  
   209  		got := commitUserParamForRepo(t, git(githubWikiBareRepo))
   210  		assert.Equal(t, currCase.wantMessage(docsDir), gitMessage(t, githubWikiBareRepo), "Case %d", i)
   211  		assert.Equal(t, currCase.want, got, "Case %d", i)
   212  		assert.Regexp(t, regexp.MustCompile(currCase.wantStdoutRegexp), buf.String(), "Case %d", i)
   213  	}
   214  }
   215  
   216  func commitUserParamForRepo(t *testing.T, g git) commitUserParam {
   217  	authorName, err := g.valueOr("", authorNameParam)
   218  	require.NoError(t, err)
   219  	authorEmail, err := g.valueOr("", authorEmailParam)
   220  	require.NoError(t, err)
   221  	committerName, err := g.valueOr("", committerNameParam)
   222  	require.NoError(t, err)
   223  	committerEmail, err := g.valueOr("", committerEmailParam)
   224  	require.NoError(t, err)
   225  	return commitUserParam{
   226  		authorName:     authorName,
   227  		authorEmail:    authorEmail,
   228  		committerName:  committerName,
   229  		committerEmail: committerEmail,
   230  	}
   231  }
   232  
   233  func gitCloneBare(t *testing.T, srcGitRepo, tmpDir string) string {
   234  	bareRepo, err := ioutil.TempDir(tmpDir, "bare-")
   235  	require.NoError(t, err)
   236  	cmd := exec.Command("git", "clone", "--bare", srcGitRepo, bareRepo)
   237  	output, err := cmd.CombinedOutput()
   238  	require.NoError(t, err, "Failed to execute %v: %v", cmd.Args, string(output))
   239  	return bareRepo
   240  }
   241  
   242  func gitMessage(t *testing.T, gitRepo string) string {
   243  	return gitCommand(t, gitRepo, "show", "-s", "--format=%B")
   244  }
   245  
   246  func gitCommitID(t *testing.T, gitRepo string) string {
   247  	return gitCommand(t, gitRepo, "rev-parse", "HEAD")
   248  }
   249  
   250  func gitCommitTime(t *testing.T, gitRepo string) string {
   251  	return gitCommand(t, gitRepo, "show", "-s", "--format=%ct")
   252  }
   253  
   254  func gitCommand(t *testing.T, gitRepo string, args ...string) string {
   255  	cmd := exec.Command("git", args...)
   256  	cmd.Dir = gitRepo
   257  	output, err := cmd.CombinedOutput()
   258  	require.NoError(t, err, "Failed to execute %v: %v", cmd.Args, string(output))
   259  	return strings.TrimSpace(string(output))
   260  }