func (s *PlatformKeysRewriteLoader) Run(context map[string]interface{}) error {
	folders := context[constants.CTX_HARDWARE_FOLDERS].([]string)

	platformKeysRewriteTxtPath, err := findPlatformKeysRewriteTxt(folders)
	if err != nil {
		return utils.WrapError(err)
	}
	if platformKeysRewriteTxtPath == constants.EMPTY_STRING {
		return nil
	}

	platformKeysRewrite := types.PlatforKeysRewrite{}
	platformKeysRewrite.Rewrites = []types.PlatforKeyRewrite{}

	txt, err := props.Load(platformKeysRewriteTxtPath)
	keys := utils.KeysOfMapOfString(txt)
	sort.Strings(keys)

	for _, key := range keys {
		keyParts := strings.Split(key, ".")
		if keyParts[0] == constants.PLATFORM_REWRITE_OLD {
			rewriteKey := strings.Join(keyParts[2:], ".")
			oldValue := txt[key]
			newValue := txt[constants.PLATFORM_REWRITE_NEW+"."+strings.Join(keyParts[1:], ".")]
			platformKeyRewrite := types.PlatforKeyRewrite{Key: rewriteKey, OldValue: oldValue, NewValue: newValue}
			platformKeysRewrite.Rewrites = append(platformKeysRewrite.Rewrites, platformKeyRewrite)
		}
	}

	context[constants.CTX_PLATFORM_KEYS_REWRITE] = platformKeysRewrite

	return nil
}
func loadBoards(boards map[string]*types.Board, packageId string, platformId string, folder string, logger i18n.Logger) error {
	properties, err := props.Load(filepath.Join(folder, constants.FILE_BOARDS_TXT), logger)
	if err != nil {
		return utils.WrapError(err)
	}

	localProperties, err := props.SafeLoad(filepath.Join(folder, constants.FILE_BOARDS_LOCAL_TXT), logger)
	if err != nil {
		return utils.WrapError(err)
	}

	properties = utils.MergeMapsOfStrings(properties, localProperties)

	propertiesByBoardId := props.FirstLevelOf(properties)
	delete(propertiesByBoardId, constants.BOARD_PROPERTIES_MENU)

	for boardId, properties := range propertiesByBoardId {
		properties[constants.ID] = boardId
		board := getOrCreateBoard(boards, boardId)
		board.Properties = utils.MergeMapsOfStrings(board.Properties, properties)
		boards[boardId] = board
	}

	return nil
}
func libraryAlreadyDownloadedAndUnpacked(targetPath string, library Library) bool {
	_, err := os.Stat(filepath.Join(targetPath, strings.Replace(library.Name, " ", "_", -1)))
	if os.IsNotExist(err) {
		return false
	}

	libProps, err := props.Load(filepath.Join(targetPath, strings.Replace(library.Name, " ", "_", -1), "library.properties"), i18n.HumanLogger{})
	if err != nil {
		return false
	}
	return libProps["version"] == library.Version || libProps["version"] == library.VersionInLibProperties
}
func TestPropertiesBoardsTxt(t *testing.T) {
	properties, err := props.Load(filepath.Join("props", "boards.txt"), i18n.HumanLogger{})

	NoError(t, err)

	require.Equal(t, "Processor", properties["menu.cpu"])
	require.Equal(t, "32256", properties["ethernet.upload.maximum_size"])
	require.Equal(t, "{build.usb_flags}", properties["robotMotor.build.extra_flags"])

	ethernet := properties.SubTree("ethernet")
	require.Equal(t, "Arduino Ethernet", ethernet[constants.LIBRARY_NAME])
}
func TestPropertiesRedBeearLabBoardsTxt(t *testing.T) {
	properties, err := props.Load(filepath.Join("props", "redbearlab_boards.txt"), i18n.HumanLogger{})

	NoError(t, err)

	require.Equal(t, 83, len(properties))
	require.Equal(t, "Blend", properties["blend.name"])
	require.Equal(t, "arduino:arduino", properties["blend.build.core"])
	require.Equal(t, "0x2404", properties["blendmicro16.pid.0"])

	ethernet := properties.SubTree("blend")
	require.Equal(t, "arduino:arduino", ethernet[constants.BUILD_PROPERTIES_BUILD_CORE])
}
func coreAlreadyDownloadedAndUnpacked(targetPath string, core Core) (bool, error) {
	corePath := filepath.Join(targetPath, core.Maintainer, core.Arch)

	_, err := os.Stat(corePath)
	if os.IsNotExist(err) {
		return false, nil
	}
	platform, err := props.Load(filepath.Join(corePath, "platform.txt"), i18n.HumanLogger{})
	if err != nil {
		return false, i18n.WrapError(err)
	}

	if core.Version != platform["version"] {
		err := os.RemoveAll(corePath)
		return false, i18n.WrapError(err)
	}

	return true, nil
}
func TestPropertiesTestTxt(t *testing.T) {
	properties, err := props.Load(filepath.Join("props", "test.txt"), i18n.HumanLogger{})

	NoError(t, err)

	require.Equal(t, 4, len(properties))
	require.Equal(t, "value = 1", properties["key"])

	switch value := runtime.GOOS; value {
	case "linux":
		require.Equal(t, "is linux", properties["which.os"])
	case "windows":
		require.Equal(t, "is windows", properties["which.os"])
	case "darwin":
		require.Equal(t, "is macosx", properties["which.os"])
	default:
		require.FailNow(t, "unsupported OS")
	}
}
func (s *PlatformKeysRewriteLoader) Run(ctx *types.Context) error {
	logger := ctx.GetLogger()
	folders := ctx.HardwareFolders

	platformKeysRewriteTxtPath, err := findPlatformKeysRewriteTxt(folders)
	if err != nil {
		return i18n.WrapError(err)
	}
	if platformKeysRewriteTxtPath == constants.EMPTY_STRING {
		return nil
	}

	platformKeysRewrite := types.PlatforKeysRewrite{}
	platformKeysRewrite.Rewrites = []types.PlatforKeyRewrite{}

	txt, err := props.Load(platformKeysRewriteTxtPath, logger)
	keys := utils.KeysOfMapOfString(txt)
	sort.Strings(keys)

	for _, key := range keys {
		keyParts := strings.Split(key, ".")
		if keyParts[0] == constants.PLATFORM_REWRITE_OLD {
			index, err := strconv.Atoi(keyParts[1])
			if err != nil {
				return i18n.WrapError(err)
			}
			rewriteKey := strings.Join(keyParts[2:], ".")
			oldValue := txt[key]
			newValue := txt[constants.PLATFORM_REWRITE_NEW+"."+strings.Join(keyParts[1:], ".")]
			platformKeyRewrite := types.PlatforKeyRewrite{Key: rewriteKey, OldValue: oldValue, NewValue: newValue}
			platformKeysRewrite.Rewrites = growSliceOfRewrites(platformKeysRewrite.Rewrites, index)
			platformKeysRewrite.Rewrites[index] = platformKeyRewrite
		}
	}

	ctx.PlatformKeyRewrites = platformKeysRewrite

	return nil
}
func makeNewLibrary(libraryFolder string, debugLevel int, logger i18n.Logger) (*types.Library, error) {
	properties, err := props.Load(filepath.Join(libraryFolder, constants.LIBRARY_PROPERTIES), logger)
	if err != nil {
		return nil, utils.WrapError(err)
	}

	if properties[constants.LIBRARY_MAINTAINER] == constants.EMPTY_STRING && properties[constants.LIBRARY_EMAIL] != constants.EMPTY_STRING {
		properties[constants.LIBRARY_MAINTAINER] = properties[constants.LIBRARY_EMAIL]
	}

	for _, propName := range LIBRARY_NOT_SO_MANDATORY_PROPERTIES {
		if properties[propName] == constants.EMPTY_STRING {
			properties[propName] = "-"
		}
	}

	library := &types.Library{}
	if stat, err := os.Stat(filepath.Join(libraryFolder, constants.LIBRARY_FOLDER_SRC)); err == nil && stat.IsDir() {
		library.Layout = types.LIBRARY_RECURSIVE
		library.SrcFolder = filepath.Join(libraryFolder, constants.LIBRARY_FOLDER_SRC)
	} else {
		library.Layout = types.LIBRARY_FLAT
		library.SrcFolder = libraryFolder
	}

	subFolders, err := utils.ReadDirFiltered(libraryFolder, utils.FilterDirs)
	if err != nil {
		return nil, utils.WrapError(err)
	}

	if debugLevel > 0 {
		for _, subFolder := range subFolders {
			if utils.IsSCCSOrHiddenFile(subFolder) {
				if !utils.IsSCCSFile(subFolder) && utils.IsHiddenFile(subFolder) {
					logger.Fprintln(os.Stdout, constants.LOG_LEVEL_WARN, constants.MSG_WARNING_SPURIOUS_FILE_IN_LIB, filepath.Base(subFolder.Name()), properties[constants.LIBRARY_NAME])
				}
			}
		}
	}

	if properties[constants.LIBRARY_ARCHITECTURES] == constants.EMPTY_STRING {
		properties[constants.LIBRARY_ARCHITECTURES] = constants.LIBRARY_ALL_ARCHS
	}
	library.Archs = []string{}
	for _, arch := range strings.Split(properties[constants.LIBRARY_ARCHITECTURES], ",") {
		library.Archs = append(library.Archs, strings.TrimSpace(arch))
	}

	properties[constants.LIBRARY_CATEGORY] = strings.TrimSpace(properties[constants.LIBRARY_CATEGORY])
	if !LIBRARY_CATEGORIES[properties[constants.LIBRARY_CATEGORY]] {
		logger.Fprintln(os.Stdout, constants.LOG_LEVEL_WARN, constants.MSG_WARNING_LIB_INVALID_CATEGORY, properties[constants.LIBRARY_CATEGORY], properties[constants.LIBRARY_NAME], constants.LIB_CATEGORY_UNCATEGORIZED)
		properties[constants.LIBRARY_CATEGORY] = constants.LIB_CATEGORY_UNCATEGORIZED
	}
	library.Category = properties[constants.LIBRARY_CATEGORY]

	if properties[constants.LIBRARY_LICENSE] == constants.EMPTY_STRING {
		properties[constants.LIBRARY_LICENSE] = constants.LIB_LICENSE_UNSPECIFIED
	}
	library.License = properties[constants.LIBRARY_LICENSE]

	library.Folder = libraryFolder
	library.Name = filepath.Base(libraryFolder)
	library.Version = strings.TrimSpace(properties[constants.LIBRARY_VERSION])
	library.Author = strings.TrimSpace(properties[constants.LIBRARY_AUTHOR])
	library.Maintainer = strings.TrimSpace(properties[constants.LIBRARY_MAINTAINER])
	library.Sentence = strings.TrimSpace(properties[constants.LIBRARY_SENTENCE])
	library.Paragraph = strings.TrimSpace(properties[constants.LIBRARY_PARAGRAPH])
	library.URL = strings.TrimSpace(properties[constants.LIBRARY_URL])
	library.IsLegacy = false
	library.DotALinkage = strings.TrimSpace(properties[constants.LIBRARY_DOT_A_LINKAGE]) == "true"
	library.Properties = properties

	return library, nil
}
func TestPropertiesBroken(t *testing.T) {
	_, err := props.Load(filepath.Join("props", "broken.txt"), i18n.HumanLogger{})

	require.Error(t, err)
}