Best Syzkaller code snippet using bisect.headCommit
git_repo_test.go
Source:git_repo_test.go
1// Copyright 2017 syzkaller project authors. All rights reserved.2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.3package vcs4import (5 "fmt"6 "io/ioutil"7 "os"8 "path/filepath"9 "sort"10 "testing"11 "time"12 "github.com/google/go-cmp/cmp"13 "github.com/google/syzkaller/pkg/osutil"14)15func init() {16 // Disable sandboxing entirely because we create test repos without sandboxing.17 os.Setenv("SYZ_DISABLE_SANDBOXING", "yes")18}19const (20 userEmail = `test@syzkaller.com`21 userName = `Test Syzkaller`22 extractFixTagsEmail = `"syzbot" <syzbot@my.mail.com>`23)24func TestGitRepo(t *testing.T) {25 t.Parallel()26 baseDir, err := ioutil.TempDir("", "syz-git-test")27 if err != nil {28 t.Fatal(err)29 }30 defer os.RemoveAll(baseDir)31 repo1 := createTestRepo(t, baseDir, "repo1")32 repo2 := createTestRepo(t, baseDir, "repo2")33 repo := newGit(filepath.Join(baseDir, "repo"), nil)34 {35 com, err := repo.Poll(repo1.dir, "master")36 if err != nil {37 t.Fatal(err)38 }39 if diff := cmp.Diff(com, repo1.commits["master"]["1"]); diff != "" {40 t.Fatal(diff)41 }42 }43 {44 com, err := repo.CheckoutBranch(repo1.dir, "branch1")45 if err != nil {46 t.Fatal(err)47 }48 if diff := cmp.Diff(com, repo1.commits["branch1"]["1"]); diff != "" {49 t.Fatal(diff)50 }51 }52 {53 want := repo1.commits["branch1"]["0"]54 com, err := repo.CheckoutCommit(repo1.dir, want.Hash)55 if err != nil {56 t.Fatal(err)57 }58 if diff := cmp.Diff(com, want); diff != "" {59 t.Fatal(diff)60 }61 }62 {63 commits, err := repo.ListRecentCommits(repo1.commits["branch1"]["1"].Hash)64 if err != nil {65 t.Fatal(err)66 }67 want := []string{"repo1-branch1-1", "repo1-branch1-0", "repo1-master-0"}68 if diff := cmp.Diff(commits, want); diff != "" {69 t.Fatal(diff)70 }71 }72 {73 want := repo2.commits["branch1"]["0"]74 com, err := repo.CheckoutCommit(repo2.dir, want.Hash)75 if err != nil {76 t.Fatal(err)77 }78 if diff := cmp.Diff(com, want); diff != "" {79 t.Fatal(diff)80 }81 }82 {83 want := repo2.commits["branch1"]["1"]84 com, err := repo.CheckoutCommit(repo2.dir, want.Hash)85 if err != nil {86 t.Fatal(err)87 }88 if diff := cmp.Diff(com, want); diff != "" {89 t.Fatal(diff)90 }91 }92 {93 com, err := repo.CheckoutBranch(repo2.dir, "branch2")94 if err != nil {95 t.Fatal(err)96 }97 if diff := cmp.Diff(com, repo2.commits["branch2"]["1"]); diff != "" {98 t.Fatal(diff)99 }100 }101 {102 want := repo2.commits["branch2"]["0"]103 com, err := repo.SwitchCommit(want.Hash)104 if err != nil {105 t.Fatal(err)106 }107 if diff := cmp.Diff(com, want); diff != "" {108 t.Fatal(diff)109 }110 }111}112func TestMetadata(t *testing.T) {113 t.Parallel()114 repoDir, err := ioutil.TempDir("", "syz-git-test")115 if err != nil {116 t.Fatal(err)117 }118 defer os.RemoveAll(repoDir)119 repo := makeTestRepo(t, repoDir)120 for i, test := range metadataTests {121 repo.commitChange(test.description)122 com, err := repo.repo.HeadCommit()123 if err != nil {124 t.Fatal(err)125 }126 checkCommit(t, i, test, com, false)127 }128 commits, err := repo.repo.ExtractFixTagsFromCommits("HEAD", extractFixTagsEmail)129 if err != nil {130 t.Fatal(err)131 }132 if len(metadataTests) != len(commits) {133 t.Fatalf("want %v commits, got %v", len(metadataTests), len(commits))134 }135 for i, test := range metadataTests {136 checkCommit(t, i, test, commits[len(commits)-i-1], true)137 for _, title := range []string{test.title, test.title2} {138 if title == "" {139 continue140 }141 com, err := repo.repo.GetCommitByTitle(title)142 if err != nil {143 t.Error(err)144 } else if com == nil {145 t.Errorf("no commits found by title %q", title)146 } else if com.Title != title {147 t.Errorf("wrong commit %q found by title %q", com.Title, title)148 }149 }150 }151}152func checkCommit(t *testing.T, idx int, test testCommit, com *Commit, checkTags bool) {153 if !checkTags {154 return155 }156 if test.title != com.Title {157 t.Errorf("#%v: want title %q, got %q", idx, test.title, com.Title)158 }159 if test.author != com.Author {160 t.Errorf("#%v: want author %q, got %q", idx, test.author, com.Author)161 }162 if userName != com.AuthorName {163 t.Errorf("#%v: want author name %q, got %q", idx, userName, com.Author)164 }165 if diff := cmp.Diff(test.cc, com.CC); diff != "" {166 t.Logf("%#v", com.CC)167 t.Error(diff)168 }169 if diff := cmp.Diff(test.tags, com.Tags); checkTags && diff != "" {170 t.Error(diff)171 }172}173type testCommit struct {174 description string175 title string176 title2 string177 author string178 cc []string179 tags []string180}181// nolint: lll182var metadataTests = []testCommit{183 {184 description: `dashboard/app: bump max repros per bug to 10185Reported-by: syzbot+8e4090902540da8c6e8f@my.mail.com186`,187 title: "dashboard/app: bump max repros per bug to 10",188 author: userEmail,189 cc: []string{userEmail},190 tags: []string{"8e4090902540da8c6e8f"},191 },192 {193 description: `executor: remove dead code194Reported-by: syzbot+8e4090902540da8c6e8f@my.mail.com195Reported-by: syzbot <syzbot+a640a0fc325c29c3efcb@my.mail.com>196`,197 title: "executor: remove dead code",198 author: userEmail,199 cc: []string{userEmail},200 tags: []string{"8e4090902540da8c6e8f", "a640a0fc325c29c3efcb"},201 },202 {203 description: `pkg/csource: fix string escaping bug204Reported-and-tested-by: syzbot+8e4090902540da8c6e8fa640a0fc325c29c3efcb@my.mail.com205Tested-by: syzbot+4234987263748623784623758235@my.mail.com206`,207 title: "pkg/csource: fix string escaping bug",208 author: userEmail,209 cc: []string{"syzbot+4234987263748623784623758235@my.mail.com", "syzbot+8e4090902540da8c6e8fa640a0fc325c29c3efcb@my.mail.com", userEmail},210 tags: []string{"8e4090902540da8c6e8fa640a0fc325c29c3efcb", "4234987263748623784623758235"},211 },212 {213 description: `When freeing a lockf struct that already is part of a linked list, make sure to update the next pointer for the preceding lock. Prevents a double free panic.214ok millert@215Reported-by: syzbot+6dd701dc797b23b8c761@my.mail.com216`,217 title: "When freeing a lockf struct that already is part of a linked list, make sure to update the next pointer for the preceding lock. Prevents a double free panic.",218 author: userEmail,219 cc: []string{userEmail},220 tags: []string{"6dd701dc797b23b8c761"},221 },222 {223 description: `ipmr: properly check rhltable_init() return value224commit 8fb472c09b9d ("ipmr: improve hash scalability")225added a call to rhltable_init() without checking its return value.226 227This problem was then later copied to IPv6 and factorized in commit2280bbbf0e7d0e7 ("ipmr, ip6mr: Unite creation of new mr_table")229 230Fixes: 8fb472c09b9d ("ipmr: improve hash scalability")231Fixes: 0bbbf0e7d0e7 ("ipmr, ip6mr: Unite creation of new mr_table")232Reported-by: syzbot+6dd701dc797b23b8c761@my.mail.com233`,234 title: "ipmr: properly check rhltable_init() return value",235 title2: "net-backports: ipmr: properly check rhltable_init() return value",236 author: userEmail,237 cc: []string{userEmail},238 tags: []string{"6dd701dc797b23b8c761"},239 },240 {241 description: `f2fs: sanity check for total valid node blocks242Reported-by: syzbot+bf9253040425feb155ad@my.mail.com243Reported-by: syzbot+bf9253040425feb155ad@my.mail.com244`,245 title: "f2fs: sanity check for total valid node blocks",246 author: userEmail,247 cc: []string{userEmail},248 tags: []string{"bf9253040425feb155ad"},249 },250 {251 description: `USB: fix usbmon BUG trigger252Automated tests triggered this by opening usbmon and accessing the253mmap while simultaneously resizing the buffers. This bug was with254us since 2006, because typically applications only size the buffers255once and thus avoid racing. Reported by Kirill A. Shutemov.256Reported-by: <syzbot+f9831b881b3e849829fc@my.mail.com>257Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>258Cc: stable <stable@vger.kernel.org>259Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>260`,261 title: "USB: fix usbmon BUG trigger",262 author: userEmail,263 cc: []string{"gregkh@linuxfoundation.org", userEmail, "zaitcev@redhat.com"},264 tags: []string{"f9831b881b3e849829fc"},265 },266}267func TestBisect(t *testing.T) {268 t.Parallel()269 repoDir, err := ioutil.TempDir("", "syz-git-test")270 if err != nil {271 t.Fatal(err)272 }273 defer os.RemoveAll(repoDir)274 repo := makeTestRepo(t, repoDir)275 var commits []string276 for i := 0; i < 5; i++ {277 repo.commitChange(fmt.Sprintf("commit %v", i))278 com, err := repo.repo.HeadCommit()279 if err != nil {280 t.Fatal(err)281 }282 commits = append(commits, com.Hash)283 t.Logf("%v %v", com.Hash, com.Title)284 }285 type Test struct {286 pred func() (BisectResult, error)287 result []string288 }289 tests := []Test{290 {291 // All are bad.292 func() (BisectResult, error) {293 return BisectBad, nil294 },295 []string{commits[1]},296 },297 {298 // All are good.299 func() (BisectResult, error) {300 return BisectGood, nil301 },302 []string{commits[4]},303 },304 {305 // All are skipped.306 func() (BisectResult, error) {307 return BisectSkip, nil308 },309 []string{commits[1], commits[2], commits[3], commits[4]},310 },311 {312 // Some are skipped.313 func() (BisectResult, error) {314 current, err := repo.repo.HeadCommit()315 if err != nil {316 t.Fatal(err)317 }318 switch current.Hash {319 case commits[1]:320 return BisectSkip, nil321 case commits[2]:322 return BisectSkip, nil323 case commits[3]:324 return BisectGood, nil325 default:326 return 0, fmt.Errorf("unknown commit %v", current.Hash)327 }328 },329 []string{commits[4]},330 },331 {332 // Some are skipped.333 func() (BisectResult, error) {334 current, err := repo.repo.HeadCommit()335 if err != nil {336 t.Fatal(err)337 }338 switch current.Hash {339 case commits[1]:340 return BisectGood, nil341 case commits[2]:342 return BisectSkip, nil343 case commits[3]:344 return BisectBad, nil345 default:346 return 0, fmt.Errorf("unknown commit %v", current.Hash)347 }348 },349 []string{commits[2], commits[3]},350 },351 {352 // Some are skipped.353 func() (BisectResult, error) {354 current, err := repo.repo.HeadCommit()355 if err != nil {356 t.Fatal(err)357 }358 switch current.Hash {359 case commits[1]:360 return BisectSkip, nil361 case commits[2]:362 return BisectSkip, nil363 case commits[3]:364 return BisectGood, nil365 default:366 return 0, fmt.Errorf("unknown commit %v", current.Hash)367 }368 },369 []string{commits[4]},370 },371 }372 for i, test := range tests {373 t.Logf("TEST %v", i)374 result, err := repo.repo.Bisect(commits[4], commits[0], (*testWriter)(t), test.pred)375 if err != nil {376 t.Fatal(err)377 }378 var got []string379 for _, com := range result {380 got = append(got, com.Hash)381 }382 sort.Strings(got) // git result order is non-deterministic (wat)383 sort.Strings(test.result)384 if diff := cmp.Diff(test.result, got); diff != "" {385 t.Logf("result: %+v", got)386 t.Fatal(diff)387 }388 }389}390type testWriter testing.T391func (t *testWriter) Write(data []byte) (int, error) {392 (*testing.T)(t).Log(string(data))393 return len(data), nil394}395func createTestRepo(t *testing.T, baseDir, name string) *testRepo {396 repo := makeTestRepo(t, filepath.Join(baseDir, name))397 repo.git("checkout", "-b", "master")398 repo.commitFileChange("master", "0")399 for _, branch := range []string{"branch1", "branch2"} {400 repo.git("checkout", "-b", branch, "master")401 repo.commitFileChange(branch, "0")402 repo.commitFileChange(branch, "1")403 }404 repo.git("checkout", "master")405 repo.commitFileChange("master", "1")406 return repo407}408type testRepo struct {409 t *testing.T410 dir string411 name string412 commits map[string]map[string]*Commit413 repo *git414}415func makeTestRepo(t *testing.T, dir string) *testRepo {416 if err := osutil.MkdirAll(dir); err != nil {417 t.Fatal(err)418 }419 ignoreCC := map[string]bool{420 "stable@vger.kernel.org": true,421 }422 repo := &testRepo{423 t: t,424 dir: dir,425 name: filepath.Base(dir),426 commits: make(map[string]map[string]*Commit),427 repo: newGit(dir, ignoreCC),428 }429 repo.git("init")430 repo.git("config", "--add", "user.email", userEmail)431 repo.git("config", "--add", "user.name", userName)432 return repo433}434func (repo *testRepo) git(args ...string) {435 if _, err := osutil.RunCmd(time.Minute, repo.dir, "git", args...); err != nil {436 repo.t.Fatal(err)437 }438}439func (repo *testRepo) commitFileChange(branch, change string) {440 id := fmt.Sprintf("%v-%v-%v", repo.name, branch, change)441 file := filepath.Join(repo.dir, "file")442 if err := osutil.WriteFile(file, []byte(id)); err != nil {443 repo.t.Fatal(err)444 }445 repo.git("add", file)446 repo.git("commit", "-m", id)447 if repo.commits[branch] == nil {448 repo.commits[branch] = make(map[string]*Commit)449 }450 com, err := repo.repo.HeadCommit()451 if err != nil {452 repo.t.Fatal(err)453 }454 repo.commits[branch][change] = com455}456func (repo *testRepo) commitChange(description string) {457 repo.git("commit", "--allow-empty", "-m", description)458}...
git.go
Source:git.go
1// Copyright 2017 syzkaller project authors. All rights reserved.2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.3package vcs4import (5 "bufio"6 "bytes"7 "fmt"8 "io"9 "net/mail"10 "os"11 "os/exec"12 "regexp"13 "sort"14 "strings"15 "time"16 "github.com/google/syzkaller/pkg/hash"17 "github.com/google/syzkaller/pkg/log"18 "github.com/google/syzkaller/pkg/osutil"19)20type git struct {21 dir string22 ignoreCC map[string]bool23}24func newGit(dir string, ignoreCC map[string]bool) *git {25 return &git{26 dir: dir,27 ignoreCC: ignoreCC,28 }29}30func (git *git) Poll(repo, branch string) (*Commit, error) {31 git.reset()32 origin, err := git.git("remote", "get-url", "origin")33 if err != nil || strings.TrimSpace(string(origin)) != repo {34 // The repo is here, but it has wrong origin (e.g. repo in config has changed), re-clone.35 if err := git.clone(repo, branch); err != nil {36 return nil, err37 }38 }39 // Use origin/branch for the case the branch was force-pushed,40 // in such case branch is not the same is origin/branch and we will41 // stuck with the local version forever (git checkout won't fail).42 if _, err := git.git("checkout", "origin/"+branch); err != nil {43 // No such branch (e.g. branch in config has changed), re-clone.44 if err := git.clone(repo, branch); err != nil {45 return nil, err46 }47 }48 if _, err := git.git("fetch"); err != nil {49 // Something else is wrong, re-clone.50 if err := git.clone(repo, branch); err != nil {51 return nil, err52 }53 }54 if _, err := git.git("checkout", "origin/"+branch); err != nil {55 return nil, err56 }57 return git.HeadCommit()58}59func (git *git) CheckoutBranch(repo, branch string) (*Commit, error) {60 git.reset()61 if _, err := git.git("reset", "--hard"); err != nil {62 if err := git.initRepo(err); err != nil {63 return nil, err64 }65 }66 _, err := git.git("fetch", repo, branch)67 if err != nil {68 return nil, err69 }70 if _, err := git.git("checkout", "FETCH_HEAD"); err != nil {71 return nil, err72 }73 return git.HeadCommit()74}75func (git *git) CheckoutCommit(repo, commit string) (*Commit, error) {76 git.reset()77 if _, err := git.git("reset", "--hard"); err != nil {78 if err := git.initRepo(err); err != nil {79 return nil, err80 }81 }82 if err := git.fetchRemote(repo); err != nil {83 return nil, err84 }85 return git.SwitchCommit(commit)86}87func (git *git) fetchRemote(repo string) error {88 repoHash := hash.String([]byte(repo))89 // Ignore error as we can double add the same remote and that will fail.90 git.git("remote", "add", repoHash, repo)91 _, err := git.git("fetch", "--tags", repoHash)92 return err93}94func (git *git) SwitchCommit(commit string) (*Commit, error) {95 git.git("reset", "--hard")96 if _, err := git.git("checkout", commit); err != nil {97 return nil, err98 }99 return git.HeadCommit()100}101func (git *git) clone(repo, branch string) error {102 if err := git.initRepo(nil); err != nil {103 return err104 }105 if _, err := git.git("remote", "add", "origin", repo); err != nil {106 return err107 }108 if _, err := git.git("fetch", "origin", branch); err != nil {109 return err110 }111 return nil112}113func (git *git) reset() {114 // This function tries to reset git repo state to a known clean state.115 git.git("reset", "--hard")116 git.git("bisect", "reset")117 git.git("reset", "--hard")118}119func (git *git) initRepo(reason error) error {120 if reason != nil {121 log.Logf(1, "git: initializing repo at %v: %v", git.dir, reason)122 }123 if err := os.RemoveAll(git.dir); err != nil {124 return fmt.Errorf("failed to remove repo dir: %v", err)125 }126 if err := osutil.MkdirAll(git.dir); err != nil {127 return fmt.Errorf("failed to create repo dir: %v", err)128 }129 if err := osutil.SandboxChown(git.dir); err != nil {130 return err131 }132 if _, err := git.git("init"); err != nil {133 return err134 }135 return nil136}137func (git *git) HeadCommit() (*Commit, error) {138 return git.getCommit("HEAD")139}140func (git *git) getCommit(commit string) (*Commit, error) {141 output, err := git.git("log", "--format=%H%n%s%n%ae%n%an%n%ad%n%b", "-n", "1", commit)142 if err != nil {143 return nil, err144 }145 return gitParseCommit(output, nil, nil, git.ignoreCC)146}147func gitParseCommit(output, user, domain []byte, ignoreCC map[string]bool) (*Commit, error) {148 lines := bytes.Split(output, []byte{'\n'})149 if len(lines) < 4 || len(lines[0]) != 40 {150 return nil, fmt.Errorf("unexpected git log output: %q", output)151 }152 const dateFormat = "Mon Jan 2 15:04:05 2006 -0700"153 date, err := time.Parse(dateFormat, string(lines[4]))154 if err != nil {155 return nil, fmt.Errorf("failed to parse date in git log output: %v\n%q", err, output)156 }157 cc := make(map[string]bool)158 cc[strings.ToLower(string(lines[2]))] = true159 var tags []string160 for _, line := range lines[5:] {161 if user != nil {162 userPos := bytes.Index(line, user)163 if userPos != -1 {164 domainPos := bytes.Index(line[userPos+len(user)+1:], domain)165 if domainPos != -1 {166 startPos := userPos + len(user)167 endPos := userPos + len(user) + domainPos + 1168 tag := string(line[startPos:endPos])169 present := false170 for _, tag1 := range tags {171 if tag1 == tag {172 present = true173 break174 }175 }176 if !present {177 tags = append(tags, tag)178 }179 }180 }181 }182 for _, re := range ccRes {183 matches := re.FindSubmatchIndex(line)184 if matches == nil {185 continue186 }187 addr, err := mail.ParseAddress(string(line[matches[2]:matches[3]]))188 if err != nil {189 break190 }191 email := strings.ToLower(addr.Address)192 if ignoreCC[email] {193 continue194 }195 cc[email] = true196 break197 }198 }199 sortedCC := make([]string, 0, len(cc))200 for addr := range cc {201 sortedCC = append(sortedCC, addr)202 }203 sort.Strings(sortedCC)204 com := &Commit{205 Hash: string(lines[0]),206 Title: string(lines[1]),207 Author: string(lines[2]),208 AuthorName: string(lines[3]),209 CC: sortedCC,210 Tags: tags,211 Date: date,212 }213 return com, nil214}215func (git *git) GetCommitByTitle(title string) (*Commit, error) {216 commits, _, err := git.GetCommitsByTitles([]string{title})217 if err != nil || len(commits) == 0 {218 return nil, err219 }220 return commits[0], nil221}222func (git *git) GetCommitsByTitles(titles []string) ([]*Commit, []string, error) {223 var greps []string224 m := make(map[string]string)225 for _, title := range titles {226 canonical := CanonicalizeCommit(title)227 greps = append(greps, canonical)228 m[canonical] = title229 }230 since := time.Now().Add(-time.Hour * 24 * 365 * 2).Format("01-02-2006")231 commits, err := git.fetchCommits(since, "HEAD", "", "", greps, true)232 if err != nil {233 return nil, nil, err234 }235 var results []*Commit236 for _, com := range commits {237 canonical := CanonicalizeCommit(com.Title)238 if orig := m[canonical]; orig != "" {239 delete(m, canonical)240 results = append(results, com)241 com.Title = orig242 }243 }244 var missing []string245 for _, orig := range m {246 missing = append(missing, orig)247 }248 return results, missing, nil249}250func (git *git) ListRecentCommits(baseCommit string) ([]string, error) {251 // On upstream kernel this produces ~11MB of output.252 // Somewhat inefficient to collect whole output in a slice253 // and then convert to string, but should be bearable.254 output, err := git.git("log", "--pretty=format:%s", "-n", "200000", baseCommit)255 if err != nil {256 return nil, err257 }258 return strings.Split(string(output), "\n"), nil259}260func (git *git) ExtractFixTagsFromCommits(baseCommit, email string) ([]*Commit, error) {261 user, domain, err := splitEmail(email)262 if err != nil {263 return nil, fmt.Errorf("failed to parse email %q: %v", email, err)264 }265 grep := user + "+.*" + domain266 since := time.Now().Add(-time.Hour * 24 * 365).Format("01-02-2006")267 return git.fetchCommits(since, baseCommit, user, domain, []string{grep}, false)268}269func (git *git) fetchCommits(since, base, user, domain string, greps []string, fixedStrings bool) ([]*Commit, error) {270 const commitSeparator = "---===syzkaller-commit-separator===---"271 args := []string{"log", "--since", since, "--format=%H%n%s%n%ae%n%an%n%ad%n%b%n" + commitSeparator}272 if fixedStrings {273 args = append(args, "--fixed-strings")274 }275 for _, grep := range greps {276 args = append(args, "--grep", grep)277 }278 args = append(args, base)279 cmd := exec.Command("git", args...)280 cmd.Dir = git.dir281 if err := osutil.Sandbox(cmd, true, false); err != nil {282 return nil, err283 }284 stdout, err := cmd.StdoutPipe()285 if err != nil {286 return nil, err287 }288 if err := cmd.Start(); err != nil {289 return nil, err290 }291 defer cmd.Wait()292 defer cmd.Process.Kill()293 var (294 s = bufio.NewScanner(stdout)295 buf = new(bytes.Buffer)296 separator = []byte(commitSeparator)297 commits []*Commit298 userBytes []byte299 domainBytes []byte300 )301 if user != "" {302 userBytes = []byte(user + "+")303 domainBytes = []byte(domain)304 }305 for s.Scan() {306 ln := s.Bytes()307 if !bytes.Equal(ln, separator) {308 buf.Write(ln)309 buf.WriteByte('\n')310 continue311 }312 com, err := gitParseCommit(buf.Bytes(), userBytes, domainBytes, git.ignoreCC)313 if err != nil {314 return nil, err315 }316 if user == "" || len(com.Tags) != 0 {317 commits = append(commits, com)318 }319 buf.Reset()320 }321 return commits, s.Err()322}323func (git *git) git(args ...string) ([]byte, error) {324 return runSandboxed(git.dir, "git", args...)325}326func splitEmail(email string) (user, domain string, err error) {327 addr, err := mail.ParseAddress(email)328 if err != nil {329 return "", "", err330 }331 at := strings.IndexByte(addr.Address, '@')332 if at == -1 {333 return "", "", fmt.Errorf("no @ in email address")334 }335 user = addr.Address[:at]336 domain = addr.Address[at:]337 if plus := strings.IndexByte(user, '+'); plus != -1 {338 user = user[:plus]339 }340 return341}342func (git *git) Bisect(bad, good string, trace io.Writer, pred func() (BisectResult, error)) ([]*Commit, error) {343 git.reset()344 firstBad, err := git.getCommit(bad)345 if err != nil {346 return nil, err347 }348 output, err := git.git("bisect", "start", bad, good)349 if err != nil {350 return nil, err351 }352 defer git.reset()353 fmt.Fprintf(trace, "# git bisect start %v %v\n%s", bad, good, output)354 current, err := git.HeadCommit()355 if err != nil {356 return nil, err357 }358 var bisectTerms = [...]string{359 BisectBad: "bad",360 BisectGood: "good",361 BisectSkip: "skip",362 }363 for {364 res, err := pred()365 // Linux EnvForCommit may cherry-pick some fixes, reset these before the next step.366 git.git("reset", "--hard")367 if err != nil {368 return nil, err369 }370 if res == BisectBad {371 firstBad = current372 }373 output, err = git.git("bisect", bisectTerms[res])374 fmt.Fprintf(trace, "# git bisect %v %v\n%s", bisectTerms[res], current.Hash, output)375 if err != nil {376 if bytes.Contains(output, []byte("There are only 'skip'ped commits left to test")) {377 return git.bisectInconclusive(output)378 }379 return nil, err380 }381 next, err := git.HeadCommit()382 if err != nil {383 return nil, err384 }385 if current.Hash == next.Hash {386 return []*Commit{firstBad}, nil387 }388 current = next389 }390}391func (git *git) bisectInconclusive(output []byte) ([]*Commit, error) {392 // For inconclusive bisection git prints the following message:393 //394 // There are only 'skip'ped commits left to test.395 // The first bad commit could be any of:396 // 1f43f400a2cbb02f3d34de8fe30075c070254816397 // 4d96e13ee9cd1f7f801e8c7f4b12f09d1da4a5d8398 // 5cd856a5ef9aa189df757c322be34ad735a5b17f399 // We cannot bisect more!400 //401 // For conclusive bisection:402 //403 // 7c3850adbcccc2c6c9e7ab23a7dcbc4926ee5b96 is the first bad commit404 var commits []*Commit405 for _, hash := range regexp.MustCompile("[a-f0-9]{40}").FindAll(output, -1) {406 com, err := git.getCommit(string(hash))407 if err != nil {408 return nil, err409 }410 commits = append(commits, com)411 }412 return commits, nil413}...
headCommit
Using AI Code Generation
1import (2func main() {3 r, err := git.PlainOpen("C:/Users/Sid/Desktop/GoGit")4 if err != nil {5 log.Fatal(err)6 }7 headCommit, err := r.Head()8 if err != nil {9 log.Fatal(err)10 }11 obj, err := r.CommitObject(headCommit.Hash())12 if err != nil {13 log.Fatal(err)14 }15 fmt.Println(obj)16}
headCommit
Using AI Code Generation
1import (2func main() {3 cmd := exec.Command("git", "bisect", "head")4 out, err := cmd.Output()5 if err != nil {6 log.Fatal(err)7 }8 fmt.Printf("%s", out)9}
headCommit
Using AI Code Generation
1import (2func main() {3 r, err := git.PlainOpen("/home/abc/go/src/github.com/abc/def")4 if err != nil {5 panic(err)6 }7 ref, err := r.Head()8 if err != nil {9 panic(err)10 }11 commit, err := r.CommitObject(ref.Hash())12 if err != nil {13 panic(err)14 }15 iter := commit.Parents()16 err = iter.ForEach(func(c *object.Commit) error {17 fmt.Println(c)18 })19 if err != nil {20 panic(err)21 }22}
headCommit
Using AI Code Generation
1import (2func main() {3 repo, err := git.OpenRepository("path to repository")4 if err != nil {5 fmt.Println("error in opening repository")6 }7 bisect, err := repo.NewBisect()8 if err != nil {9 fmt.Println("error in creating bisect object")10 }11 headCommit, err := bisect.HeadCommit()12 if err != nil {13 fmt.Println("error in getting head commit")14 }15 fmt.Println("head commit is ", headCommit)16}
headCommit
Using AI Code Generation
1import (2func main() {3 r, err := git.PlainOpen(".")4 if err != nil {5 fmt.Println(err)6 os.Exit(1)7 }8 head, err := r.Head()9 if err != nil {10 fmt.Println(err)11 os.Exit(1)12 }13 commit, err := r.CommitObject(head.Hash())14 if err != nil {15 fmt.Println(err)16 os.Exit(1)17 }18 fmt.Println(commit)19}20import (21func main() {22 r, err := git.PlainOpen(".")23 if err != nil {24 fmt.Println(err)25 os.Exit(1)26 }27 ref, err := r.Head()28 if err != nil {29 fmt.Println(err)30 os.Exit(1)31 }32 commit, err := r.CommitObject(ref.Hash())33 if err != nil {34 fmt.Println(err)35 os.Exit(1)36 }37 fmt.Println(commit)38}39import (40func main() {41 r, err := git.PlainOpen(".")42 if err != nil {43 fmt.Println(err)44 os.Exit(1)45 }46 commitIter, err := r.Log(&git.LogOptions{})47 if err != nil {48 fmt.Println(err)49 os.Exit(1)50 }
headCommit
Using AI Code Generation
1import (2func main() {3 repo, err := git.OpenRepository(os.Args[1])4 if err != nil {5 fmt.Println(err)6 }7 headCommit, err := repo.HeadCommit()8 if err != nil {9 fmt.Println(err)10 }11 fmt.Println("Head commit is:", headCommit.Id().String())12}
headCommit
Using AI Code Generation
1import (2func main() {3 repo, _ := git.OpenRepository("/home/username/.git")4 bisect := git.InitBisect(repo)5 commit, _ := bisect.HeadCommit()6 fmt.Println(commit)7}
headCommit
Using AI Code Generation
1import (2func main() {3 b := bisect.New()4 head, err := b.HeadCommit()5 if err != nil {6 fmt.Println(err)7 }8 fmt.Println(head)9}10&{7c3c3e3e7a9
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!