func generateProjectWorkDirName(project *common.Project) { project.WorkDir = ConfigSections.Common.DirProjectsWorkDir + "/" + fmt.Sprintf("%d", time.Now().UnixNano()) + "_" + project.Name + "_workdir" // also update to mongo var change mgo.Change // update project status change = mgo.Change{ ReturnNew: true, Update: bson.M{ "$set": bson.M{ "work_dir": project.WorkDir, }}} if changeInfo, err := mgoPrjectsCollection.FindId(project.Id).Apply(change, project); err != nil { glog.Error("error updating project workdir : ", err) glog.Error("changeInfo = ", changeInfo) } }
// scan and update to mongodb func scanProjectTree(project *common.Project, cancelChannel chan bool) { // call sync first before walk var execCmd *exec.Cmd = exec.Command("sync") err := execCmd.Start() if err != nil { glog.V(1).Info("Failed to run sync") } time.Sleep(2 * time.Second) // project.TotalSize = 0 // to store size On Disk glog.V(1).Info("Start walkdir :", project.WorkDir) //itemsList := make ([]common.TreePath, 0, 1000000) itemsList := make([]interface{}, 0, 1000000) rootLen := len(project.WorkDir) isCancel := false err = filepath.Walk(project.WorkDir, func(path string, info os.FileInfo, err error) error { //callback function //glog.V(1).Info ("walk callback is called") select { case <-cancelChannel: isCancel = true return errors.New("User canceled ") default: if err != nil { glog.V(1).Info("Tree walk err :", err) return err } // last element baseName := info.Name() if info.IsDir() && baseName == ".git" { return filepath.SkipDir // skip version control directories } endSlice := len(path) - len(baseName) if rootLen > endSlice { // the base directory itself return nil } // add to list which will be later inserted into mongo var treePath common.TreePath treePath.Id = bson.NewObjectId() treePath.Name = baseName treePath.ProjectId = project.Id treePath.Path = path[rootLen : endSlice-1] treePath.FullPath = treePath.Path + "/" + treePath.Name treePath.IsDir = info.IsDir() if info.IsDir() { treePath.Size = 0 } else { treePath.Size = info.Size() } itemsList = append(itemsList, treePath) //glog.V(1).Info ("add :", path, " ", treePath.Path," ", baseName) //glog.V(1).Info ("walk :"+treePath.FullPath) project.TotalSize = project.TotalSize + info.Size() } return nil }) if err != nil { if isCancel { updateProjectMessageAndStatus(project, "Project was cancelled", "error") } else { glog.V(1).Info("Error scanning project dir :", err) updateProjectMessageAndStatus(project, "There was error scanning the source tree", "error") } return } // insert the whole list to mongo - bulk insert? glog.V(1).Info("dirwalk completed. insert list into db") err1 := mgoProjectTreesCollection.Insert(itemsList...) if err1 != nil { glog.Error("Error insert list of treewalk items into db :", err1) updateProjectMessageAndStatus(project, "There was error updating directory tree items to database", "error") return } glog.V(1).Info("total size: ", project.TotalSize) // update project size, project status and message change := mgo.Change{ ReturnNew: true, Update: bson.M{ "$set": bson.M{ "message": "Analyzing files for definitions and references", "status": "analyzing", "total_size": project.TotalSize, }}} if _, err := mgoPrjectsCollection.FindId(project.Id).Apply(change, project); err != nil { glog.Error("error updating project message : ", err) //glog.Error ("changeInfo = ", changeInfo ) } // ensureIndex on project_id and fullpath go func() { index := mgo.Index{ Key: []string{"project_id", "full_path"}, Unique: true, Background: true, // see explanation here http://godoc.org/gopkg.in/mgo.v2#Query.Apply } err := mgoProjectTreesCollection.EnsureIndex(index) if err != nil { glog.Error("Error ensure index for projectTrees :", err) } }() return }