remote.go 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. package git
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "gopkg.in/src-d/go-git.v4/config"
  8. "gopkg.in/src-d/go-git.v4/plumbing"
  9. "gopkg.in/src-d/go-git.v4/plumbing/format/packfile"
  10. "gopkg.in/src-d/go-git.v4/plumbing/object"
  11. "gopkg.in/src-d/go-git.v4/plumbing/protocol/packp"
  12. "gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
  13. "gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/sideband"
  14. "gopkg.in/src-d/go-git.v4/plumbing/revlist"
  15. "gopkg.in/src-d/go-git.v4/plumbing/storer"
  16. "gopkg.in/src-d/go-git.v4/plumbing/transport"
  17. "gopkg.in/src-d/go-git.v4/plumbing/transport/client"
  18. "gopkg.in/src-d/go-git.v4/storage"
  19. "gopkg.in/src-d/go-git.v4/storage/memory"
  20. "gopkg.in/src-d/go-git.v4/utils/ioutil"
  21. )
  22. var (
  23. NoErrAlreadyUpToDate = errors.New("already up-to-date")
  24. ErrDeleteRefNotSupported = errors.New("server does not support delete-refs")
  25. ErrForceNeeded = errors.New("some refs were not updated")
  26. )
  27. const (
  28. // This describes the maximum number of commits to walk when
  29. // computing the haves to send to a server, for each ref in the
  30. // repo containing this remote, when not using the multi-ack
  31. // protocol. Setting this to 0 means there is no limit.
  32. maxHavesToVisitPerRef = 100
  33. )
  34. // Remote represents a connection to a remote repository.
  35. type Remote struct {
  36. c *config.RemoteConfig
  37. s storage.Storer
  38. }
  39. func newRemote(s storage.Storer, c *config.RemoteConfig) *Remote {
  40. return &Remote{s: s, c: c}
  41. }
  42. // Config returns the RemoteConfig object used to instantiate this Remote.
  43. func (r *Remote) Config() *config.RemoteConfig {
  44. return r.c
  45. }
  46. func (r *Remote) String() string {
  47. var fetch, push string
  48. if len(r.c.URLs) > 0 {
  49. fetch = r.c.URLs[0]
  50. push = r.c.URLs[0]
  51. }
  52. return fmt.Sprintf("%s\t%s (fetch)\n%[1]s\t%[3]s (push)", r.c.Name, fetch, push)
  53. }
  54. // Push performs a push to the remote. Returns NoErrAlreadyUpToDate if the
  55. // remote was already up-to-date.
  56. func (r *Remote) Push(o *PushOptions) error {
  57. return r.PushContext(context.Background(), o)
  58. }
  59. // PushContext performs a push to the remote. Returns NoErrAlreadyUpToDate if
  60. // the remote was already up-to-date.
  61. //
  62. // The provided Context must be non-nil. If the context expires before the
  63. // operation is complete, an error is returned. The context only affects to the
  64. // transport operations.
  65. func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
  66. if err := o.Validate(); err != nil {
  67. return err
  68. }
  69. if o.RemoteName != r.c.Name {
  70. return fmt.Errorf("remote names don't match: %s != %s", o.RemoteName, r.c.Name)
  71. }
  72. s, err := newSendPackSession(r.c.URLs[0], o.Auth)
  73. if err != nil {
  74. return err
  75. }
  76. defer ioutil.CheckClose(s, &err)
  77. ar, err := s.AdvertisedReferences()
  78. if err != nil {
  79. return err
  80. }
  81. remoteRefs, err := ar.AllReferences()
  82. if err != nil {
  83. return err
  84. }
  85. isDelete := false
  86. allDelete := true
  87. for _, rs := range o.RefSpecs {
  88. if rs.IsDelete() {
  89. isDelete = true
  90. } else {
  91. allDelete = false
  92. }
  93. if isDelete && !allDelete {
  94. break
  95. }
  96. }
  97. if isDelete && !ar.Capabilities.Supports(capability.DeleteRefs) {
  98. return ErrDeleteRefNotSupported
  99. }
  100. localRefs, err := r.references()
  101. if err != nil {
  102. return err
  103. }
  104. req, err := r.newReferenceUpdateRequest(o, localRefs, remoteRefs, ar)
  105. if err != nil {
  106. return err
  107. }
  108. if len(req.Commands) == 0 {
  109. return NoErrAlreadyUpToDate
  110. }
  111. objects := objectsToPush(req.Commands)
  112. haves, err := referencesToHashes(remoteRefs)
  113. if err != nil {
  114. return err
  115. }
  116. stop, err := r.s.Shallow()
  117. if err != nil {
  118. return err
  119. }
  120. // if we have shallow we should include this as part of the objects that
  121. // we are aware.
  122. haves = append(haves, stop...)
  123. var hashesToPush []plumbing.Hash
  124. // Avoid the expensive revlist operation if we're only doing deletes.
  125. if !allDelete {
  126. hashesToPush, err = revlist.Objects(r.s, objects, haves)
  127. if err != nil {
  128. return err
  129. }
  130. }
  131. rs, err := pushHashes(ctx, s, r.s, req, hashesToPush, r.useRefDeltas(ar))
  132. if err != nil {
  133. return err
  134. }
  135. if err = rs.Error(); err != nil {
  136. return err
  137. }
  138. return r.updateRemoteReferenceStorage(req, rs)
  139. }
  140. func (r *Remote) useRefDeltas(ar *packp.AdvRefs) bool {
  141. return !ar.Capabilities.Supports(capability.OFSDelta)
  142. }
  143. func (r *Remote) newReferenceUpdateRequest(
  144. o *PushOptions,
  145. localRefs []*plumbing.Reference,
  146. remoteRefs storer.ReferenceStorer,
  147. ar *packp.AdvRefs,
  148. ) (*packp.ReferenceUpdateRequest, error) {
  149. req := packp.NewReferenceUpdateRequestFromCapabilities(ar.Capabilities)
  150. if o.Progress != nil {
  151. req.Progress = o.Progress
  152. if ar.Capabilities.Supports(capability.Sideband64k) {
  153. req.Capabilities.Set(capability.Sideband64k)
  154. } else if ar.Capabilities.Supports(capability.Sideband) {
  155. req.Capabilities.Set(capability.Sideband)
  156. }
  157. }
  158. if err := r.addReferencesToUpdate(o.RefSpecs, localRefs, remoteRefs, req); err != nil {
  159. return nil, err
  160. }
  161. return req, nil
  162. }
  163. func (r *Remote) updateRemoteReferenceStorage(
  164. req *packp.ReferenceUpdateRequest,
  165. result *packp.ReportStatus,
  166. ) error {
  167. for _, spec := range r.c.Fetch {
  168. for _, c := range req.Commands {
  169. if !spec.Match(c.Name) {
  170. continue
  171. }
  172. local := spec.Dst(c.Name)
  173. ref := plumbing.NewHashReference(local, c.New)
  174. switch c.Action() {
  175. case packp.Create, packp.Update:
  176. if err := r.s.SetReference(ref); err != nil {
  177. return err
  178. }
  179. case packp.Delete:
  180. if err := r.s.RemoveReference(local); err != nil {
  181. return err
  182. }
  183. }
  184. }
  185. }
  186. return nil
  187. }
  188. // FetchContext fetches references along with the objects necessary to complete
  189. // their histories.
  190. //
  191. // Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
  192. // no changes to be fetched, or an error.
  193. //
  194. // The provided Context must be non-nil. If the context expires before the
  195. // operation is complete, an error is returned. The context only affects to the
  196. // transport operations.
  197. func (r *Remote) FetchContext(ctx context.Context, o *FetchOptions) error {
  198. _, err := r.fetch(ctx, o)
  199. return err
  200. }
  201. // Fetch fetches references along with the objects necessary to complete their
  202. // histories.
  203. //
  204. // Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
  205. // no changes to be fetched, or an error.
  206. func (r *Remote) Fetch(o *FetchOptions) error {
  207. return r.FetchContext(context.Background(), o)
  208. }
  209. func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.ReferenceStorer, err error) {
  210. if o.RemoteName == "" {
  211. o.RemoteName = r.c.Name
  212. }
  213. if err = o.Validate(); err != nil {
  214. return nil, err
  215. }
  216. if len(o.RefSpecs) == 0 {
  217. o.RefSpecs = r.c.Fetch
  218. }
  219. s, err := newUploadPackSession(r.c.URLs[0], o.Auth)
  220. if err != nil {
  221. return nil, err
  222. }
  223. defer ioutil.CheckClose(s, &err)
  224. ar, err := s.AdvertisedReferences()
  225. if err != nil {
  226. return nil, err
  227. }
  228. req, err := r.newUploadPackRequest(o, ar)
  229. if err != nil {
  230. return nil, err
  231. }
  232. remoteRefs, err := ar.AllReferences()
  233. if err != nil {
  234. return nil, err
  235. }
  236. localRefs, err := r.references()
  237. if err != nil {
  238. return nil, err
  239. }
  240. refs, err := calculateRefs(o.RefSpecs, remoteRefs, o.Tags)
  241. if err != nil {
  242. return nil, err
  243. }
  244. req.Wants, err = getWants(r.s, refs)
  245. if len(req.Wants) > 0 {
  246. req.Haves, err = getHaves(localRefs, remoteRefs, r.s)
  247. if err != nil {
  248. return nil, err
  249. }
  250. if err = r.fetchPack(ctx, o, s, req); err != nil {
  251. return nil, err
  252. }
  253. }
  254. updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs, o.Tags, o.Force)
  255. if err != nil {
  256. return nil, err
  257. }
  258. if !updated {
  259. return remoteRefs, NoErrAlreadyUpToDate
  260. }
  261. return remoteRefs, nil
  262. }
  263. func newUploadPackSession(url string, auth transport.AuthMethod) (transport.UploadPackSession, error) {
  264. c, ep, err := newClient(url)
  265. if err != nil {
  266. return nil, err
  267. }
  268. return c.NewUploadPackSession(ep, auth)
  269. }
  270. func newSendPackSession(url string, auth transport.AuthMethod) (transport.ReceivePackSession, error) {
  271. c, ep, err := newClient(url)
  272. if err != nil {
  273. return nil, err
  274. }
  275. return c.NewReceivePackSession(ep, auth)
  276. }
  277. func newClient(url string) (transport.Transport, *transport.Endpoint, error) {
  278. ep, err := transport.NewEndpoint(url)
  279. if err != nil {
  280. return nil, nil, err
  281. }
  282. c, err := client.NewClient(ep)
  283. if err != nil {
  284. return nil, nil, err
  285. }
  286. return c, ep, err
  287. }
  288. func (r *Remote) fetchPack(ctx context.Context, o *FetchOptions, s transport.UploadPackSession,
  289. req *packp.UploadPackRequest) (err error) {
  290. reader, err := s.UploadPack(ctx, req)
  291. if err != nil {
  292. return err
  293. }
  294. defer ioutil.CheckClose(reader, &err)
  295. if err = r.updateShallow(o, reader); err != nil {
  296. return err
  297. }
  298. if err = packfile.UpdateObjectStorage(r.s,
  299. buildSidebandIfSupported(req.Capabilities, reader, o.Progress),
  300. ); err != nil {
  301. return err
  302. }
  303. return err
  304. }
  305. func (r *Remote) addReferencesToUpdate(
  306. refspecs []config.RefSpec,
  307. localRefs []*plumbing.Reference,
  308. remoteRefs storer.ReferenceStorer,
  309. req *packp.ReferenceUpdateRequest,
  310. ) error {
  311. // This references dictionary will be used to search references by name.
  312. refsDict := make(map[string]*plumbing.Reference)
  313. for _, ref := range localRefs {
  314. refsDict[ref.Name().String()] = ref
  315. }
  316. for _, rs := range refspecs {
  317. if rs.IsDelete() {
  318. if err := r.deleteReferences(rs, remoteRefs, req); err != nil {
  319. return err
  320. }
  321. } else {
  322. err := r.addOrUpdateReferences(rs, localRefs, refsDict, remoteRefs, req)
  323. if err != nil {
  324. return err
  325. }
  326. }
  327. }
  328. return nil
  329. }
  330. func (r *Remote) addOrUpdateReferences(
  331. rs config.RefSpec,
  332. localRefs []*plumbing.Reference,
  333. refsDict map[string]*plumbing.Reference,
  334. remoteRefs storer.ReferenceStorer,
  335. req *packp.ReferenceUpdateRequest,
  336. ) error {
  337. // If it is not a wilcard refspec we can directly search for the reference
  338. // in the references dictionary.
  339. if !rs.IsWildcard() {
  340. ref, ok := refsDict[rs.Src()]
  341. if !ok {
  342. return nil
  343. }
  344. return r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, req)
  345. }
  346. for _, ref := range localRefs {
  347. err := r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, req)
  348. if err != nil {
  349. return err
  350. }
  351. }
  352. return nil
  353. }
  354. func (r *Remote) deleteReferences(rs config.RefSpec,
  355. remoteRefs storer.ReferenceStorer, req *packp.ReferenceUpdateRequest) error {
  356. iter, err := remoteRefs.IterReferences()
  357. if err != nil {
  358. return err
  359. }
  360. return iter.ForEach(func(ref *plumbing.Reference) error {
  361. if ref.Type() != plumbing.HashReference {
  362. return nil
  363. }
  364. if rs.Dst("") != ref.Name() {
  365. return nil
  366. }
  367. cmd := &packp.Command{
  368. Name: ref.Name(),
  369. Old: ref.Hash(),
  370. New: plumbing.ZeroHash,
  371. }
  372. req.Commands = append(req.Commands, cmd)
  373. return nil
  374. })
  375. }
  376. func (r *Remote) addReferenceIfRefSpecMatches(rs config.RefSpec,
  377. remoteRefs storer.ReferenceStorer, localRef *plumbing.Reference,
  378. req *packp.ReferenceUpdateRequest) error {
  379. if localRef.Type() != plumbing.HashReference {
  380. return nil
  381. }
  382. if !rs.Match(localRef.Name()) {
  383. return nil
  384. }
  385. cmd := &packp.Command{
  386. Name: rs.Dst(localRef.Name()),
  387. Old: plumbing.ZeroHash,
  388. New: localRef.Hash(),
  389. }
  390. remoteRef, err := remoteRefs.Reference(cmd.Name)
  391. if err == nil {
  392. if remoteRef.Type() != plumbing.HashReference {
  393. //TODO: check actual git behavior here
  394. return nil
  395. }
  396. cmd.Old = remoteRef.Hash()
  397. } else if err != plumbing.ErrReferenceNotFound {
  398. return err
  399. }
  400. if cmd.Old == cmd.New {
  401. return nil
  402. }
  403. if !rs.IsForceUpdate() {
  404. if err := checkFastForwardUpdate(r.s, remoteRefs, cmd); err != nil {
  405. return err
  406. }
  407. }
  408. req.Commands = append(req.Commands, cmd)
  409. return nil
  410. }
  411. func (r *Remote) references() ([]*plumbing.Reference, error) {
  412. var localRefs []*plumbing.Reference
  413. iter, err := r.s.IterReferences()
  414. if err != nil {
  415. return nil, err
  416. }
  417. for {
  418. ref, err := iter.Next()
  419. if err == io.EOF {
  420. break
  421. }
  422. if err != nil {
  423. return nil, err
  424. }
  425. localRefs = append(localRefs, ref)
  426. }
  427. return localRefs, nil
  428. }
  429. func getRemoteRefsFromStorer(remoteRefStorer storer.ReferenceStorer) (
  430. map[plumbing.Hash]bool, error) {
  431. remoteRefs := map[plumbing.Hash]bool{}
  432. iter, err := remoteRefStorer.IterReferences()
  433. if err != nil {
  434. return nil, err
  435. }
  436. err = iter.ForEach(func(ref *plumbing.Reference) error {
  437. if ref.Type() != plumbing.HashReference {
  438. return nil
  439. }
  440. remoteRefs[ref.Hash()] = true
  441. return nil
  442. })
  443. if err != nil {
  444. return nil, err
  445. }
  446. return remoteRefs, nil
  447. }
  448. // getHavesFromRef populates the given `haves` map with the given
  449. // reference, and up to `maxHavesToVisitPerRef` ancestor commits.
  450. func getHavesFromRef(
  451. ref *plumbing.Reference,
  452. remoteRefs map[plumbing.Hash]bool,
  453. s storage.Storer,
  454. haves map[plumbing.Hash]bool,
  455. ) error {
  456. h := ref.Hash()
  457. if haves[h] {
  458. return nil
  459. }
  460. // No need to load the commit if we know the remote already
  461. // has this hash.
  462. if remoteRefs[h] {
  463. haves[h] = true
  464. return nil
  465. }
  466. commit, err := object.GetCommit(s, h)
  467. if err != nil {
  468. // Ignore the error if this isn't a commit.
  469. haves[ref.Hash()] = true
  470. return nil
  471. }
  472. // Until go-git supports proper commit negotiation during an
  473. // upload pack request, include up to `maxHavesToVisitPerRef`
  474. // commits from the history of each ref.
  475. walker := object.NewCommitPreorderIter(commit, haves, nil)
  476. toVisit := maxHavesToVisitPerRef
  477. return walker.ForEach(func(c *object.Commit) error {
  478. haves[c.Hash] = true
  479. toVisit--
  480. // If toVisit starts out at 0 (indicating there is no
  481. // max), then it will be negative here and we won't stop
  482. // early.
  483. if toVisit == 0 || remoteRefs[c.Hash] {
  484. return storer.ErrStop
  485. }
  486. return nil
  487. })
  488. }
  489. func getHaves(
  490. localRefs []*plumbing.Reference,
  491. remoteRefStorer storer.ReferenceStorer,
  492. s storage.Storer,
  493. ) ([]plumbing.Hash, error) {
  494. haves := map[plumbing.Hash]bool{}
  495. // Build a map of all the remote references, to avoid loading too
  496. // many parent commits for references we know don't need to be
  497. // transferred.
  498. remoteRefs, err := getRemoteRefsFromStorer(remoteRefStorer)
  499. if err != nil {
  500. return nil, err
  501. }
  502. for _, ref := range localRefs {
  503. if haves[ref.Hash()] {
  504. continue
  505. }
  506. if ref.Type() != plumbing.HashReference {
  507. continue
  508. }
  509. err = getHavesFromRef(ref, remoteRefs, s, haves)
  510. if err != nil {
  511. return nil, err
  512. }
  513. }
  514. var result []plumbing.Hash
  515. for h := range haves {
  516. result = append(result, h)
  517. }
  518. return result, nil
  519. }
  520. const refspecAllTags = "+refs/tags/*:refs/tags/*"
  521. func calculateRefs(
  522. spec []config.RefSpec,
  523. remoteRefs storer.ReferenceStorer,
  524. tagMode TagMode,
  525. ) (memory.ReferenceStorage, error) {
  526. if tagMode == AllTags {
  527. spec = append(spec, refspecAllTags)
  528. }
  529. refs := make(memory.ReferenceStorage)
  530. for _, s := range spec {
  531. if err := doCalculateRefs(s, remoteRefs, refs); err != nil {
  532. return nil, err
  533. }
  534. }
  535. return refs, nil
  536. }
  537. func doCalculateRefs(
  538. s config.RefSpec,
  539. remoteRefs storer.ReferenceStorer,
  540. refs memory.ReferenceStorage,
  541. ) error {
  542. iter, err := remoteRefs.IterReferences()
  543. if err != nil {
  544. return err
  545. }
  546. var matched bool
  547. err = iter.ForEach(func(ref *plumbing.Reference) error {
  548. if !s.Match(ref.Name()) {
  549. return nil
  550. }
  551. if ref.Type() == plumbing.SymbolicReference {
  552. target, err := storer.ResolveReference(remoteRefs, ref.Name())
  553. if err != nil {
  554. return err
  555. }
  556. ref = plumbing.NewHashReference(ref.Name(), target.Hash())
  557. }
  558. if ref.Type() != plumbing.HashReference {
  559. return nil
  560. }
  561. matched = true
  562. if err := refs.SetReference(ref); err != nil {
  563. return err
  564. }
  565. if !s.IsWildcard() {
  566. return storer.ErrStop
  567. }
  568. return nil
  569. })
  570. if !matched && !s.IsWildcard() {
  571. return fmt.Errorf("couldn't find remote ref %q", s.Src())
  572. }
  573. return err
  574. }
  575. func getWants(localStorer storage.Storer, refs memory.ReferenceStorage) ([]plumbing.Hash, error) {
  576. wants := map[plumbing.Hash]bool{}
  577. for _, ref := range refs {
  578. hash := ref.Hash()
  579. exists, err := objectExists(localStorer, ref.Hash())
  580. if err != nil {
  581. return nil, err
  582. }
  583. if !exists {
  584. wants[hash] = true
  585. }
  586. }
  587. var result []plumbing.Hash
  588. for h := range wants {
  589. result = append(result, h)
  590. }
  591. return result, nil
  592. }
  593. func objectExists(s storer.EncodedObjectStorer, h plumbing.Hash) (bool, error) {
  594. _, err := s.EncodedObject(plumbing.AnyObject, h)
  595. if err == plumbing.ErrObjectNotFound {
  596. return false, nil
  597. }
  598. return true, err
  599. }
  600. func checkFastForwardUpdate(s storer.EncodedObjectStorer, remoteRefs storer.ReferenceStorer, cmd *packp.Command) error {
  601. if cmd.Old == plumbing.ZeroHash {
  602. _, err := remoteRefs.Reference(cmd.Name)
  603. if err == plumbing.ErrReferenceNotFound {
  604. return nil
  605. }
  606. if err != nil {
  607. return err
  608. }
  609. return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String())
  610. }
  611. ff, err := isFastForward(s, cmd.Old, cmd.New)
  612. if err != nil {
  613. return err
  614. }
  615. if !ff {
  616. return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String())
  617. }
  618. return nil
  619. }
  620. func isFastForward(s storer.EncodedObjectStorer, old, new plumbing.Hash) (bool, error) {
  621. c, err := object.GetCommit(s, new)
  622. if err != nil {
  623. return false, err
  624. }
  625. found := false
  626. iter := object.NewCommitPreorderIter(c, nil, nil)
  627. err = iter.ForEach(func(c *object.Commit) error {
  628. if c.Hash != old {
  629. return nil
  630. }
  631. found = true
  632. return storer.ErrStop
  633. })
  634. return found, err
  635. }
  636. func (r *Remote) newUploadPackRequest(o *FetchOptions,
  637. ar *packp.AdvRefs) (*packp.UploadPackRequest, error) {
  638. req := packp.NewUploadPackRequestFromCapabilities(ar.Capabilities)
  639. if o.Depth != 0 {
  640. req.Depth = packp.DepthCommits(o.Depth)
  641. if err := req.Capabilities.Set(capability.Shallow); err != nil {
  642. return nil, err
  643. }
  644. }
  645. if o.Progress == nil && ar.Capabilities.Supports(capability.NoProgress) {
  646. if err := req.Capabilities.Set(capability.NoProgress); err != nil {
  647. return nil, err
  648. }
  649. }
  650. isWildcard := true
  651. for _, s := range o.RefSpecs {
  652. if !s.IsWildcard() {
  653. isWildcard = false
  654. break
  655. }
  656. }
  657. if isWildcard && o.Tags == TagFollowing && ar.Capabilities.Supports(capability.IncludeTag) {
  658. if err := req.Capabilities.Set(capability.IncludeTag); err != nil {
  659. return nil, err
  660. }
  661. }
  662. return req, nil
  663. }
  664. func buildSidebandIfSupported(l *capability.List, reader io.Reader, p sideband.Progress) io.Reader {
  665. var t sideband.Type
  666. switch {
  667. case l.Supports(capability.Sideband):
  668. t = sideband.Sideband
  669. case l.Supports(capability.Sideband64k):
  670. t = sideband.Sideband64k
  671. default:
  672. return reader
  673. }
  674. d := sideband.NewDemuxer(t, reader)
  675. d.Progress = p
  676. return d
  677. }
  678. func (r *Remote) updateLocalReferenceStorage(
  679. specs []config.RefSpec,
  680. fetchedRefs, remoteRefs memory.ReferenceStorage,
  681. tagMode TagMode,
  682. force bool,
  683. ) (updated bool, err error) {
  684. isWildcard := true
  685. forceNeeded := false
  686. for _, spec := range specs {
  687. if !spec.IsWildcard() {
  688. isWildcard = false
  689. }
  690. for _, ref := range fetchedRefs {
  691. if !spec.Match(ref.Name()) {
  692. continue
  693. }
  694. if ref.Type() != plumbing.HashReference {
  695. continue
  696. }
  697. localName := spec.Dst(ref.Name())
  698. old, _ := storer.ResolveReference(r.s, localName)
  699. new := plumbing.NewHashReference(localName, ref.Hash())
  700. // If the ref exists locally as a branch and force is not specified,
  701. // only update if the new ref is an ancestor of the old
  702. if old != nil && old.Name().IsBranch() && !force && !spec.IsForceUpdate() {
  703. ff, err := isFastForward(r.s, old.Hash(), new.Hash())
  704. if err != nil {
  705. return updated, err
  706. }
  707. if !ff {
  708. forceNeeded = true
  709. continue
  710. }
  711. }
  712. refUpdated, err := checkAndUpdateReferenceStorerIfNeeded(r.s, new, old)
  713. if err != nil {
  714. return updated, err
  715. }
  716. if refUpdated {
  717. updated = true
  718. }
  719. }
  720. }
  721. if tagMode == NoTags {
  722. return updated, nil
  723. }
  724. tags := fetchedRefs
  725. if isWildcard {
  726. tags = remoteRefs
  727. }
  728. tagUpdated, err := r.buildFetchedTags(tags)
  729. if err != nil {
  730. return updated, err
  731. }
  732. if tagUpdated {
  733. updated = true
  734. }
  735. if err == nil && forceNeeded {
  736. err = ErrForceNeeded
  737. }
  738. return
  739. }
  740. func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) (updated bool, err error) {
  741. for _, ref := range refs {
  742. if !ref.Name().IsTag() {
  743. continue
  744. }
  745. _, err := r.s.EncodedObject(plumbing.AnyObject, ref.Hash())
  746. if err == plumbing.ErrObjectNotFound {
  747. continue
  748. }
  749. if err != nil {
  750. return false, err
  751. }
  752. refUpdated, err := updateReferenceStorerIfNeeded(r.s, ref)
  753. if err != nil {
  754. return updated, err
  755. }
  756. if refUpdated {
  757. updated = true
  758. }
  759. }
  760. return
  761. }
  762. // List the references on the remote repository.
  763. func (r *Remote) List(o *ListOptions) (rfs []*plumbing.Reference, err error) {
  764. s, err := newUploadPackSession(r.c.URLs[0], o.Auth)
  765. if err != nil {
  766. return nil, err
  767. }
  768. defer ioutil.CheckClose(s, &err)
  769. ar, err := s.AdvertisedReferences()
  770. if err != nil {
  771. return nil, err
  772. }
  773. allRefs, err := ar.AllReferences()
  774. if err != nil {
  775. return nil, err
  776. }
  777. refs, err := allRefs.IterReferences()
  778. if err != nil {
  779. return nil, err
  780. }
  781. var resultRefs []*plumbing.Reference
  782. refs.ForEach(func(ref *plumbing.Reference) error {
  783. resultRefs = append(resultRefs, ref)
  784. return nil
  785. })
  786. return resultRefs, nil
  787. }
  788. func objectsToPush(commands []*packp.Command) []plumbing.Hash {
  789. var objects []plumbing.Hash
  790. for _, cmd := range commands {
  791. if cmd.New == plumbing.ZeroHash {
  792. continue
  793. }
  794. objects = append(objects, cmd.New)
  795. }
  796. return objects
  797. }
  798. func referencesToHashes(refs storer.ReferenceStorer) ([]plumbing.Hash, error) {
  799. iter, err := refs.IterReferences()
  800. if err != nil {
  801. return nil, err
  802. }
  803. var hs []plumbing.Hash
  804. err = iter.ForEach(func(ref *plumbing.Reference) error {
  805. if ref.Type() != plumbing.HashReference {
  806. return nil
  807. }
  808. hs = append(hs, ref.Hash())
  809. return nil
  810. })
  811. if err != nil {
  812. return nil, err
  813. }
  814. return hs, nil
  815. }
  816. func pushHashes(
  817. ctx context.Context,
  818. sess transport.ReceivePackSession,
  819. s storage.Storer,
  820. req *packp.ReferenceUpdateRequest,
  821. hs []plumbing.Hash,
  822. useRefDeltas bool,
  823. ) (*packp.ReportStatus, error) {
  824. rd, wr := io.Pipe()
  825. req.Packfile = rd
  826. config, err := s.Config()
  827. if err != nil {
  828. return nil, err
  829. }
  830. done := make(chan error)
  831. go func() {
  832. e := packfile.NewEncoder(wr, s, useRefDeltas)
  833. if _, err := e.Encode(hs, config.Pack.Window); err != nil {
  834. done <- wr.CloseWithError(err)
  835. return
  836. }
  837. done <- wr.Close()
  838. }()
  839. rs, err := sess.ReceivePack(ctx, req)
  840. if err != nil {
  841. return nil, err
  842. }
  843. if err := <-done; err != nil {
  844. return nil, err
  845. }
  846. return rs, nil
  847. }
  848. func (r *Remote) updateShallow(o *FetchOptions, resp *packp.UploadPackResponse) error {
  849. if o.Depth == 0 || len(resp.Shallows) == 0 {
  850. return nil
  851. }
  852. shallows, err := r.s.Shallow()
  853. if err != nil {
  854. return err
  855. }
  856. outer:
  857. for _, s := range resp.Shallows {
  858. for _, oldS := range shallows {
  859. if s == oldS {
  860. continue outer
  861. }
  862. }
  863. shallows = append(shallows, s)
  864. }
  865. return r.s.SetShallow(shallows)
  866. }