Merge lp:~mvo/snappy/snappy-atomic-write-once into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by Michael Vogt
Status: Merged
Approved by: Michael Vogt
Approved revision: 574
Merged at revision: 607
Proposed branch: lp:~mvo/snappy/snappy-atomic-write-once
Merge into: lp:~snappy-dev/snappy/snappy-moved-to-github
Diff against target: 217 lines (+29/-100)
3 files modified
partition/bootloader_uboot.go (+21/-90)
partition/bootloader_uboot_test.go (+8/-2)
partition/utils.go (+0/-8)
To merge this branch: bzr merge lp:~mvo/snappy/snappy-atomic-write-once
Reviewer Review Type Date Requested Status
Michael Vogt (community) Approve
Sergio Schvezov Approve
Review via email: mp+264125@code.launchpad.net

Commit message

Refactor partition code to use helpers.AtomicWrite() instead of duplicating that code.

Description of the change

This branch refactors the partition code a bit to use helpers.AtomicWriteFile() so that we only have a single implementation of this and not duplicate code.

To post a comment you must log in.
Revision history for this message
Sergio Schvezov (sergiusens) wrote :

Looks good, but I didn't do any live testing so not top approving

review: Approve
Revision history for this message
Snappy Tarmac (snappydevtarmac) wrote :

Attempt to merge into lp:snappy failed due to conflicts:

text conflict in partition/bootloader_uboot.go

573. By Michael Vogt

merged lp:snappy and resolved conflicts

574. By Michael Vogt

add error checking to all writes

Revision history for this message
Michael Vogt (mvo) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'partition/bootloader_uboot.go'
2--- partition/bootloader_uboot.go 2015-07-23 18:10:51 +0000
3+++ partition/bootloader_uboot.go 2015-07-24 12:00:08 +0000
4@@ -21,9 +21,9 @@
5
6 import (
7 "bufio"
8+ "bytes"
9 "fmt"
10 "os"
11- "path/filepath"
12 "strings"
13
14 "launchpad.net/snappy/helpers"
15@@ -56,7 +56,8 @@
16 bootloaderUbootStampFile = bootloaderUbootStampFileReal
17 bootloaderUbootEnvFile = bootloaderUbootEnvFileReal
18 bootloaderUbootFwEnvFile = bootloaderUbootFwEnvFileReal
19- atomicFileUpdate = atomicFileUpdateImpl
20+
21+ atomicWriteFile = helpers.AtomicWriteFile
22 )
23
24 const bootloaderNameUboot bootloaderName = "u-boot"
25@@ -198,30 +199,6 @@
26 return bootloaderUbootDir
27 }
28
29-// Write lines to file atomically. File does not have to preexist.
30-// FIXME: put into utils package
31-func atomicFileUpdateImpl(file string, lines []string) (err error) {
32- tmpFile := fmt.Sprintf("%s.NEW", file)
33-
34- // XXX: if go switches to use aio_fsync, we need to open the dir for writing
35- dir, err := os.Open(filepath.Dir(file))
36- if err != nil {
37- return err
38- }
39- defer dir.Close()
40-
41- if err := writeLines(lines, tmpFile); err != nil {
42- return err
43- }
44-
45- // atomic update
46- if err := os.Rename(tmpFile, file); err != nil {
47- return err
48- }
49-
50- return dir.Sync()
51-}
52-
53 // Rewrite the specified file, applying the specified set of changes.
54 // Lines not in the changes slice are left alone.
55 // If the original file does not contain any of the name entries (from
56@@ -230,19 +207,22 @@
57 //
58 // FIXME: put into utils package
59 // FIXME: improve logic
60-func modifyNameValueFile(file string, changes []configFileChange) (err error) {
61+func modifyNameValueFile(path string, changes []configFileChange) error {
62 var updated []configFileChange
63
64- lines, err := readLines(file)
65- if err != nil {
66- return err
67- }
68-
69- var new []string
70 // we won't write to a file if we don't need to.
71 updateNeeded := false
72
73- for _, line := range lines {
74+ file, err := os.Open(path)
75+ if err != nil {
76+ return err
77+ }
78+ defer file.Close()
79+
80+ buf := bytes.NewBuffer(nil)
81+ scanner := bufio.NewScanner(file)
82+ for scanner.Scan() {
83+ line := scanner.Text()
84 for _, change := range changes {
85 if strings.HasPrefix(line, fmt.Sprintf("%s=", change.Name)) {
86 value := strings.SplitN(line, "=", 2)[1]
87@@ -255,11 +235,11 @@
88 }
89 }
90 }
91- new = append(new, line)
92+ if _, err := fmt.Fprintln(buf, line); err != nil {
93+ return err
94+ }
95 }
96
97- lines = new
98-
99 for _, change := range changes {
100 got := false
101 for _, update := range updated {
102@@ -274,64 +254,15 @@
103
104 // name/value pair did not exist in original
105 // file, so append
106- lines = append(lines, fmt.Sprintf("%s=%s",
107- change.Name, change.Value))
108+ if _, err := fmt.Fprintf(buf, "%s=%s\n", change.Name, change.Value); err != nil {
109+ return err
110+ }
111 }
112 }
113
114 if updateNeeded {
115- return atomicFileUpdate(file, lines)
116+ return atomicWriteFile(path, buf.Bytes(), 0644)
117 }
118
119 return nil
120 }
121-
122-// FIXME: put into utils package
123-func readLines(path string) (lines []string, err error) {
124-
125- file, err := os.Open(path)
126-
127- if err != nil {
128- return nil, err
129- }
130-
131- defer file.Close()
132-
133- scanner := bufio.NewScanner(file)
134- for scanner.Scan() {
135- lines = append(lines, scanner.Text())
136- }
137-
138- return lines, scanner.Err()
139-}
140-
141-// FIXME: put into utils package
142-func writeLines(lines []string, path string) (err error) {
143-
144- file, err := os.Create(path)
145-
146- if err != nil {
147- return err
148- }
149-
150- defer func() {
151- e := file.Close()
152- if err == nil {
153- err = e
154- }
155- }()
156-
157- writer := bufio.NewWriter(file)
158-
159- for _, line := range lines {
160- if _, err := fmt.Fprintln(writer, line); err != nil {
161- return err
162- }
163- }
164-
165- if err := writer.Flush(); err != nil {
166- return err
167- }
168-
169- return file.Sync()
170-}
171
172=== modified file 'partition/bootloader_uboot_test.go'
173--- partition/bootloader_uboot_test.go 2015-07-23 18:10:51 +0000
174+++ partition/bootloader_uboot_test.go 2015-07-24 12:00:08 +0000
175@@ -291,7 +291,10 @@
176 s.makeFakeUbootEnv(c)
177
178 atomiCall := false
179- atomicFileUpdate = func(a string, b []string) error { atomiCall = true; return atomicFileUpdateImpl(a, b) }
180+ atomicWriteFile = func(a string, b []byte, c os.FileMode) error {
181+ atomiCall = true
182+ return helpers.AtomicWriteFile(a, b, c)
183+ }
184
185 partition := New()
186 u := newUboot(partition)
187@@ -308,7 +311,10 @@
188 c.Assert(ioutil.WriteFile(bootloaderUbootEnvFile, []byte(""), 0644), IsNil)
189
190 atomiCall := false
191- atomicFileUpdate = func(a string, b []string) error { atomiCall = true; return atomicFileUpdateImpl(a, b) }
192+ atomicWriteFile = func(a string, b []byte, c os.FileMode) error {
193+ atomiCall = true
194+ return helpers.AtomicWriteFile(a, b, c)
195+ }
196
197 partition := New()
198 u := newUboot(partition)
199
200=== modified file 'partition/utils.go'
201--- partition/utils.go 2015-06-11 08:26:37 +0000
202+++ partition/utils.go 2015-07-24 12:00:08 +0000
203@@ -26,14 +26,6 @@
204 "strings"
205 )
206
207-// Run the commandline specified by the args array chrooted to the given dir
208-var runInChroot = func(chrootDir string, args ...string) (err error) {
209- fullArgs := []string{"/usr/sbin/chroot", chrootDir}
210- fullArgs = append(fullArgs, args...)
211-
212- return runCommand(fullArgs...)
213-}
214-
215 // FIXME: would it make sense to differenciate between launch errors and
216 // exit code? (i.e. something like (returnCode, error) ?)
217 func runCommandImpl(args ...string) (err error) {

Subscribers

People subscribed via source and target branches