[from now] 2014/10/18 00:10:20

diff --git a/cmd/copybackup/copybackup.go b/cmd/copybackup/copybackup.go
index 7c65cd9..fb931ba 100644
--- a/cmd/copybackup/copybackup.go
+++ b/cmd/copybackup/copybackup.go
@@ -15,15 +15,15 @@ import (
 	core "github.com/yukimemi/gocore"
 )

-type Options struct {
+type Options struct { // {{{
 	Generation int    `short:"g" long:"generation" description:"バックアップする世代。(デフォルト: 5)" default:"5"`
 	BackupDst  string `short:"b" long:"backup" description:"バックアップを保存する先。(デフォルト: _old)" default:"_old"`
-	Sleep      int    `short:"s" long:"sleep" description:"バックアップ間隔。[秒] (デフォルト: 300)" default:"60*5"`
+	Sleep      int    `short:"s" long:"sleep" description:"バックアップ間隔。[秒] (デフォルト: -1 (繰り返さない))" default:"-1"`
 	Csv        string `short:"c" long:"csv" description:"設定ファイルから読み込み。(csvファイル)"`
 	Help       bool   `short:"h" long:"help" description:"このヘルプを表示。"`
-}
+} // }}}

-func showHelp() {
+func showHelp() { // {{{

 	os.Stderr.WriteString(`
 Usage: copybackup [options] [FILE | DIRECTORY | input csv file]
@@ -49,10 +49,10 @@ Options:
 			tag.Get("description"),
 		)
 	}
-}
+} // }}}

-func main() {
-	core.Logger, _ = log.NewLogger(os.Stdout, log.TIME_FORMAT_SEC, log.LOG_FORMAT_POWERFUL, log.LogLevel_Debug)
+func main() { // {{{
+	core.Logger, _ = log.NewLogger(os.Stdout, log.TIME_FORMAT_SEC, log.LOG_FORMAT_POWERFUL, log.LogLevel_Info)

 	var e error
 	var st int
@@ -60,6 +60,7 @@ func main() {
 	var wg sync.WaitGroup

 	cpus := runtime.NumCPU()
+	core.Logger.Debugf("cpu num = [%d]", cpus)
 	semaphore := make(chan int, cpus)

 	opts := new(Options)
@@ -73,47 +74,51 @@ func main() {
 	}

 	if opts.Help {
-		// parser.WriteHelp(os.Stderr)
 		showHelp()
 		return
 	}

 	if len(args) == 0 {
-		// parser.WriteHelp(os.Stderr)
 		showHelp()
 		return
 	}

-	for _, arg := range args {
-		if f, e := os.Stat(arg); f.IsDir() {
-			files, e := ioutil.ReadDir(arg)
-			core.FailOnError(e)
-			for _, f := range files {
-				if !f.IsDir() {
-					wg.Add(1)
-					go func() {
-						defer wg.Done()
-						semaphore <- 1
-						cg := cb.NewCopyGroup(filepath.Join(arg, f.Name()), opts.BackupDst, opts.Generation, opts.Sleep)
-						cg.Backup()
-						cg.DeleteOldFile()
-						<-semaphore
-					}()
+	for {
+		for _, arg := range args {
+			if f, e := os.Stat(arg); f.IsDir() {
+				files, e := ioutil.ReadDir(arg)
+				core.FailOnError(e)
+				for _, f := range files {
+					if !f.IsDir() {
+						src := filepath.Join(arg, f.Name())
+						wg.Add(1)
+						go func() {
+							defer wg.Done()
+							semaphore <- 1
+							cg := cb.NewCopyGroup(src, opts.BackupDst, opts.Generation)
+							cg.Backup()
+							cg.DeleteOldFile()
+							<-semaphore
+						}()
+					}
 				}
+			} else if e != nil {
+				core.FailOnError(e)
+			} else {
+				cg := cb.NewCopyGroup(arg, opts.BackupDst, opts.Generation)
+				wg.Add(1)
+				go func() {
+					defer wg.Done()
+					semaphore <- 1
+					cg.Backup()
+					cg.DeleteOldFile()
+					<-semaphore
+				}()
 			}
-		} else if e != nil {
-			core.FailOnError(e)
-		} else {
-			cg := cb.NewCopyGroup(arg, opts.BackupDst, opts.Generation, opts.Sleep)
-			wg.Add(1)
-			go func() {
-				defer wg.Done()
-				semaphore <- 1
-				cg.Backup()
-				cg.DeleteOldFile()
-				<-semaphore
-			}()
 		}
+		wg.Wait()
+
+		fmt.Printf("%d 秒後に再バックアップ処理を行います。'q'を押すと終了します。\n", opts.Sleep)
+
 	}
-	wg.Wait()
-}
+} // }}}
diff --git a/copybackup.go b/copybackup.go
index a4ac3f3..06732bd 100644
--- a/copybackup.go
+++ b/copybackup.go
@@ -18,7 +18,6 @@ type CopyGroup struct { // {{{
 	dst        string
 	bkpath     string
 	generation int
-	sleep      int
 } // }}}

 func makeDstPath(src, bkpath string) (string, error) { // {{{
@@ -41,10 +40,12 @@ func makeDstPath(src, bkpath string) (string, error) { // {{{
 	return dst, e
 } // }}}

-func NewCopyGroup(src, bkpath string, generation, sleep int) *CopyGroup { // {{{
+func NewCopyGroup(src, bkpath string, generation int) *CopyGroup { // {{{
+	// core.Logger.Debugf("src = [%s]", src)
 	dst, e := makeDstPath(src, bkpath)
+	// core.Logger.Debugf("dst = [%s]", dst)
 	core.FailOnError(e)
-	return &CopyGroup{src, dst, bkpath, generation, sleep}
+	return &CopyGroup{src, dst, bkpath, generation}
 } // }}}

 func (cg *CopyGroup) Backup() error { // {{{
@@ -57,6 +58,8 @@ func (cg *CopyGroup) Backup() error { // {{{
 	if latestFile != "" {
 		l, _ := os.Stat(latestFile)
 		s, _ := os.Stat(cg.src)
+		core.Logger.Debugf("src = [%s], time = [%s]", s.Name(), s.ModTime().Format(time.StampMilli))
+		core.Logger.Debugf("latestFile = [%s], time = [%s]", l.Name(), l.ModTime().Format(time.StampMilli))
 		if l.ModTime().Equal(s.ModTime()) {
 			core.Logger.Debugf("[%s] is same as [%s]", cg.src, latestFile)
 			return nil
@@ -116,12 +119,13 @@ func (cg *CopyGroup) getLatestFile() (string, error) { // {{{
 		return "", nil
 	}

-	latestFile = files[0]
 	for _, file := range files {
 		m, e := regexp.MatchString(matchs, file.Name())
 		core.FailOnError(e)
 		if m {
-			if latestFile.ModTime().Before(file.ModTime()) {
+			if latestFile == nil {
+				latestFile = file
+			} else if latestFile.ModTime().Before(file.ModTime()) {
 				latestFile = file
 			}
 		}
@@ -145,12 +149,13 @@ func (cg *CopyGroup) getOldestFile() (string, error) { // {{{
 		return "", nil
 	}

-	oldestFile = files[0]
 	for _, file := range files {
 		m, e := regexp.MatchString(matchs, file.Name())
 		core.FailOnError(e)
 		if m {
-			if oldestFile.ModTime().After(file.ModTime()) {
+			if oldestFile == nil {
+				oldestFile = file
+			} else if oldestFile.ModTime().After(file.ModTime()) {
 				oldestFile = file
 			}
 		}
diff --git a/copybackup_test.go b/copybackup_test.go
index 7e99c01..1f5488c 100644
--- a/copybackup_test.go
+++ b/copybackup_test.go
@@ -1,6 +1,7 @@
 package copybackup

 import (
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"regexp"
@@ -12,6 +13,7 @@ import (
 )

 const THIS_FILE_NAME string = "copybackup_test.go"
+const DUMMY_FILE_NAME string = "DUMMY.dmy"
 const GENERATION = 3
 const TEST_FILES_COUNT = 6

@@ -19,21 +21,27 @@ var cg *CopyGroup
 var files []string
 var oldestFileExpected string
 var latestFileExpected string
+var dummy1 string
+var dummy2 string

 func init() { // {{{
 	core.Logger, _ = log.NewLogger(os.Stdout, log.TIME_FORMAT_SEC, log.LOG_FORMAT_POWERFUL, log.LogLevel_Debug)
 	pwd, _ := os.Getwd()
 	src := filepath.Join(pwd, THIS_FILE_NAME)
 	files = make([]string, 0)
-	cg = NewCopyGroup(src, "_old", GENERATION, 60)
+	cg = NewCopyGroup(src, "_old", GENERATION)
 	dstDir := filepath.Dir(cg.dst)
 	if _, e := os.Stat(dstDir); e == nil {
 		os.RemoveAll(dstDir)
 	}
 	os.MkdirAll(dstDir, os.ModePerm)

+	dummy1 = filepath.Join(pwd, "_old", DUMMY_FILE_NAME+"1")
+	core.Logger.Debugf("dummy1 = [%s]", dummy1)
+	ioutil.WriteFile(dummy1, []byte("DUMMY"), os.ModePerm)
+
 	for i := 0; i < TEST_FILES_COUNT; i++ {
-		cg = NewCopyGroup(src, "_old", GENERATION, 60)
+		cg = NewCopyGroup(src, "_old", GENERATION)
 		cp(cg.dst, cg.src)
 		os.Chtimes(cg.dst, time.Now(), time.Now())
 		if i == 0 {
@@ -44,6 +52,11 @@ func init() { // {{{
 		files = append(files, cg.dst)
 		time.Sleep(time.Second)
 	}
+
+	dummy2 = filepath.Join(pwd, "_old", DUMMY_FILE_NAME+"2")
+	core.Logger.Debugf("dummy2 = [%s]", dummy2)
+	ioutil.WriteFile(dummy2, []byte("DUMMY"), os.ModePerm)
+
 } // }}}

 func TestMakeDstPath1(t *testing.T) { // {{{
@@ -107,28 +120,32 @@ func TestGetLatestFile(t *testing.T) { // {{{

 func TestDeleteOldFile1(t *testing.T) { // {{{
 	pwd, _ := os.Getwd()
-	cg := NewCopyGroup(filepath.Join(pwd, THIS_FILE_NAME), "_old", -1, 60)
+	cg := NewCopyGroup(filepath.Join(pwd, THIS_FILE_NAME), "_old", -1)
 	cg.DeleteOldFile()
-	count := cg.countMatchFiles()
-	expected := TEST_FILES_COUNT

-	if count != expected {
-		t.Errorf("expected = [%d] but count = [%d]", expected, count)
+	if _, e := os.Stat(oldestFileExpected); e != nil {
+		t.Errorf("[%s] expects exists, but it was deleted !", oldestFileExpected)
+	} else if _, e := os.Stat(dummy1); e != nil {
+		t.Errorf("[%s] expects exists, but it was deleted !", dummy1)
+	} else if _, e := os.Stat(dummy2); e != nil {
+		t.Errorf("[%s] expects exists, but it was deleted !", dummy2)
 	}
 } // }}}

 func TestDeleteOldFile2(t *testing.T) { // {{{
 	cg.DeleteOldFile()
-	count := cg.countMatchFiles()
-	expected := GENERATION

-	if count != expected {
-		t.Errorf("expected = [%d] but count = [%d]", expected, count)
+	if _, e := os.Stat(oldestFileExpected); e == nil {
+		t.Errorf("[%s] expects deleted, but it is exists !", oldestFileExpected)
+	} else if _, e := os.Stat(dummy1); e != nil {
+		t.Errorf("[%s] expects exists, but it was deleted !", dummy1)
+	} else if _, e := os.Stat(dummy2); e != nil {
+		t.Errorf("[%s] expects exists, but it was deleted !", dummy2)
 	}
 } // }}}

 func TestBackup(t *testing.T) { // {{{
-	cg := NewCopyGroup(cg.src, cg.bkpath, cg.generation, cg.sleep)
+	cg := NewCopyGroup(cg.src, cg.bkpath, cg.generation)
 	cg.Backup()
 	count := cg.countMatchFiles()
 	expected := GENERATION + 1