text:
/*	$NetBSD: miivar.h,v 1.8 1999/04/23 04:24:32 thorpej Exp $	*/

/*-
 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: releng/9.3/sys/dev/mii/miivar.h 230711 2012-01-29 01:01:32Z marius $
 */

#ifndef _DEV_MII_MIIVAR_H_
#define	_DEV_MII_MIIVAR_H_

#include <sys/queue.h>

/*
 * Media Independent Interface data structure defintions
 */

struct mii_softc;

/*
 * Callbacks from MII layer into network interface device driver.
 */
typedef	int (*mii_readreg_t)(struct device *, int, int);
typedef	void (*mii_writereg_t)(struct device *, int, int, int);
typedef	void (*mii_statchg_t)(struct device *);

/*
 * A network interface driver has one of these structures in its softc.
 * It is the interface from the network interface driver to the MII
 * layer.
 */
struct mii_data {
	struct ifmedia mii_media;	/* media information */
	struct ifnet *mii_ifp;		/* pointer back to network interface */

	/*
	 * For network interfaces with multiple PHYs, a list of all
	 * PHYs is required so they can all be notified when a media
	 * request is made.
	 */
	LIST_HEAD(mii_listhead, mii_softc) mii_phys;
	u_int mii_instance;

	/*
	 * PHY driver fills this in with active media status.
	 */
	u_int mii_media_status;
	u_int mii_media_active;

	/*
	 * Calls from MII layer into network interface driver.
	 */
	mii_readreg_t mii_readreg;
	mii_writereg_t mii_writereg;
	mii_statchg_t mii_statchg;
};
typedef struct mii_data mii_data_t;

/*
 * Functions provided by the PHY to perform various functions.
 */
struct mii_phy_funcs {
	int (*pf_service)(struct mii_softc *, struct mii_data *, int);
	void (*pf_status)(struct mii_softc *);
	void (*pf_reset)(struct mii_softc *);
};

/*
 * Requests that can be made to the downcall.
 */
#define	MII_TICK	1	/* once-per-second tick */
#define	MII_MEDIACHG	2	/* user changed media; perform the switch */
#define	MII_POLLSTAT	3	/* user requested media status; fill it in */

/*
 * Each PHY driver's softc has one of these as the first member.
 * XXX This would be better named "phy_softc", but this is the name
 * XXX BSDI used, and we would like to have the same interface.
 */
struct mii_softc {
	device_t mii_dev;		/* generic device glue */

	LIST_ENTRY(mii_softc) mii_list;	/* entry on parent's PHY list */

	uint32_t mii_mpd_oui;		/* the PHY's OUI (MII_OUI())*/
	uint32_t mii_mpd_model;		/* the PHY's model (MII_MODEL())*/
	uint32_t mii_mpd_rev;		/* the PHY's revision (MII_REV())*/
	u_int mii_capmask;		/* capability mask for BMSR */
	u_int mii_phy;			/* our MII address */
	u_int mii_offset;		/* first PHY, second PHY, etc. */
	u_int mii_inst;			/* instance for ifmedia */

	/* Our PHY functions. */
	const struct mii_phy_funcs *mii_funcs;

	struct mii_data *mii_pdata;	/* pointer to parent's mii_data */

	u_int mii_flags;		/* misc. flags; see below */
	u_int mii_capabilities;		/* capabilities from BMSR */
	u_int mii_extcapabilities;	/* extended capabilities */
	u_int mii_ticks;		/* MII_TICK counter */
	u_int mii_anegticks;		/* ticks before retrying aneg */
	u_int mii_media_active;		/* last active media */
	u_int mii_media_status;		/* last active status */
};
typedef struct mii_softc mii_softc_t;

/* mii_flags */
#define	MIIF_INITDONE	0x00000001	/* has been initialized (mii_data) */
#define	MIIF_NOISOLATE	0x00000002	/* do not isolate the PHY */
#if 0
#define	MIIF_NOLOOP	0x00000004	/* no loopback capability */
#endif
#define	MIIF_DOINGAUTO	0x00000008	/* doing autonegotiation (mii_softc) */
#define	MIIF_AUTOTSLEEP	0x00000010	/* use tsleep(), not callout() */
#define	MIIF_HAVEFIBER	0x00000020	/* from parent: has fiber interface */
#define	MIIF_HAVE_GTCR	0x00000040	/* has 100base-T2/1000base-T CR */
#define	MIIF_IS_1000X	0x00000080	/* is a 1000BASE-X device */
#define	MIIF_DOPAUSE	0x00000100	/* advertise PAUSE capability */
#define	MIIF_IS_HPNA	0x00000200	/* is a HomePNA device */
#define	MIIF_FORCEANEG	0x00000400	/* force auto-negotiation */
#define	MIIF_NOMANPAUSE	0x00100000	/* no manual PAUSE selection */
#define	MIIF_FORCEPAUSE	0x00200000	/* force PAUSE advertisement */
#define	MIIF_MACPRIV0	0x01000000	/* private to the MAC driver */
#define	MIIF_MACPRIV1	0x02000000	/* private to the MAC driver */
#define	MIIF_MACPRIV2	0x04000000	/* private to the MAC driver */
#define	MIIF_PHYPRIV0	0x10000000	/* private to the PHY driver */
#define	MIIF_PHYPRIV1	0x20000000	/* private to the PHY driver */
#define	MIIF_PHYPRIV2	0x40000000	/* private to the PHY driver */

/* Default mii_anegticks values */
#define	MII_ANEGTICKS		5
#define	MII_ANEGTICKS_GIGE	17

#define	MIIF_INHERIT_MASK	(MIIF_NOISOLATE|MIIF_NOLOOP|MIIF_AUTOTSLEEP)

/*
 * Special `locators' passed to mii_attach().  If one of these is not
 * an `any' value, we look for *that* PHY and configure it.  If both
 * are not `any', that is an error, and mii_attach() will fail.
 */
#define	MII_OFFSET_ANY		-1
#define	MII_PHY_ANY		-1

/*
 * Used to attach a PHY to a parent.
 */
struct mii_attach_args {
	struct mii_data *mii_data;	/* pointer to parent data */
	u_int mii_phyno;		/* MII address */
	u_int mii_offset;		/* first PHY, second PHY, etc. */
	uint32_t mii_id1;		/* PHY ID register 1 */
	uint32_t mii_id2;		/* PHY ID register 2 */
	u_int mii_capmask;		/* capability mask for BMSR */
};
typedef struct mii_attach_args mii_attach_args_t;

/*
 * Used to match a PHY.
 */
struct mii_phydesc {
	uint32_t mpd_oui;		/* the PHY's OUI */
	uint32_t mpd_model;		/* the PHY's model */
	const char *mpd_name;		/* the PHY's name */
};
#define MII_PHY_DESC(a, b) { MII_OUI_ ## a, MII_MODEL_ ## a ## _ ## b, \
	MII_STR_ ## a ## _ ## b }
#define MII_PHY_END	{ 0, 0, NULL }

/*
 * An array of these structures map MII media types to BMCR/ANAR settings.
 */
struct mii_media {
	u_int	mm_bmcr;		/* BMCR settings for this media */
	u_int	mm_anar;		/* ANAR settings for this media */
	u_int	mm_gtcr;		/* 100base-T2 or 1000base-T CR */
};

#define	MII_MEDIA_NONE		0
#define	MII_MEDIA_10_T		1
#define	MII_MEDIA_10_T_FDX	2
#define	MII_MEDIA_100_T4	3
#define	MII_MEDIA_100_TX	4
#define	MII_MEDIA_100_TX_FDX	5
#define	MII_MEDIA_1000_X	6
#define	MII_MEDIA_1000_X_FDX	7
#define	MII_MEDIA_1000_T	8
#define	MII_MEDIA_1000_T_FDX	9
#define	MII_NMEDIA		10

#ifdef _KERNEL

#define PHY_READ(p, r) \
	MIIBUS_READREG((p)->mii_dev, (p)->mii_phy, (r))

#define PHY_WRITE(p, r, v) \
	MIIBUS_WRITEREG((p)->mii_dev, (p)->mii_phy, (r), (v))

#define	PHY_SERVICE(p, d, o) \
	(*(p)->mii_funcs->pf_service)((p), (d), (o))

#define	PHY_STATUS(p) \
	(*(p)->mii_funcs->pf_status)(p)

#define	PHY_RESET(p) \
	(*(p)->mii_funcs->pf_reset)(p)

enum miibus_device_ivars {
	MIIBUS_IVAR_FLAGS
};

/*
 * Simplified accessors for miibus
 */
#define	MIIBUS_ACCESSOR(var, ivar, type)				\
	__BUS_ACCESSOR(miibus, var, MIIBUS, ivar, type)

MIIBUS_ACCESSOR(flags,		FLAGS,		u_int)

extern devclass_t	miibus_devclass;
extern driver_t		miibus_driver;

int	mii_attach(device_t, device_t *, struct ifnet *, ifm_change_cb_t,
	    ifm_stat_cb_t, int, int, int, int);
void	mii_down(struct mii_data *);
int	mii_mediachg(struct mii_data *);
void	mii_tick(struct mii_data *);
void	mii_pollstat(struct mii_data *);
void	mii_phy_add_media(struct mii_softc *);

int	mii_phy_auto(struct mii_softc *);
int	mii_phy_detach(device_t dev);
void	mii_phy_down(struct mii_softc *);
u_int	mii_phy_flowstatus(struct mii_softc *);
void	mii_phy_reset(struct mii_softc *);
void	mii_phy_setmedia(struct mii_softc *sc);
void	mii_phy_update(struct mii_softc *, int);
int	mii_phy_tick(struct mii_softc *);

const struct mii_phydesc * mii_phy_match(const struct mii_attach_args *ma,
    const struct mii_phydesc *mpd);
const struct mii_phydesc * mii_phy_match_gen(const struct mii_attach_args *ma,
    const struct mii_phydesc *mpd, size_t endlen);
int mii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv);
void mii_phy_dev_attach(device_t dev, u_int flags,
    const struct mii_phy_funcs *mpf, int add_media);

void	ukphy_status(struct mii_softc *);

u_int	mii_oui(u_int, u_int);
#define	MII_OUI(id1, id2)	mii_oui(id1, id2)
#define	MII_MODEL(id2)		(((id2) & IDR2_MODEL) >> 4)
#define	MII_REV(id2)		((id2) & IDR2_REV)

#endif /* _KERNEL */

#endif /* _DEV_MII_MIIVAR_H_ */


text:
<?php

/**
 * Doctrine_Util
 *
 * @package     Doctrine
 * @subpackage  Util
 * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @link        www.doctrine-project.org
 * @since       1.0
 * @version     $Revision$
 * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
 */
class Doctrine_Util extends Doctrine_Connection_Module
{ }

redpajama_set_name: RedPajamaGithub


text:
require 'dfp_api'

def get_all_companies(dfp)
  company_service = dfp.service(:CompanyService, API_VERSION)

  # Create a statement to select companies.
  statement = dfp.new_statement_builder()

  # Retrieve a small amount of companies at a time, paging
  # through until all companies have been retrieved.
  page = {:total_result_set_size => 0}
  begin
    page = company_service.get_companies_by_statement(
        statement.to_statement()
    )

    # Print out some information for each company.
    unless page[:results].nil?
      page[:results].each_with_index do |company, index|
        puts '%d) Company with ID %d, name "%s", and type "%s" was found.' %
            [index + statement.offset, company[:id], company[:name],
            company[:type]]
      end
    end

    # Increase the statement offset by the page size to get the next page.
    statement.offset += statement.limit
  end while statement.offset < page[:total_result_set_size]

  puts 'Total number of companies: %d' % page[:total_result_set_size]
end

if __FILE__ == $0
  API_VERSION = :v201711

  # Get DfpApi instance and load configuration from ~/dfp_api.yml.
  dfp = DfpApi::Api.new

  # To enable logging of SOAP requests, set the log_level value to 'DEBUG' in
  # the configuration file or provide your own logger:
  # dfp.logger = Logger.new('dfp_xml.log')

  begin
    get_all_companies(dfp)

  # HTTP errors.
  rescue AdsCommon::Errors::HttpError => e
    puts "HTTP Error: %s" % e

  # API errors.
  rescue DfpApi::Errors::ApiException => e
    puts "Message: %s" % e.message
    puts 'Errors:'
    e.errors.each_with_index do |error, index|
      puts "\tError [%d]:" % (index + 1)
      error.each do |field, value|
        puts "\t\t%s: %s" % [field, value]
      end
    end
  end
end


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<TITLE>
AStarHeuristic
</TITLE>

<META NAME="date" CONTENT="2010-06-15">

<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">

      Package
    Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

  All Classes

  SUMMARY: NESTED | FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD

Class AStarHeuristic

java.lang.Object
  AStarHeuristic

public class AStarHeuristic
extends java.lang.Object

A heuristic that uses the tile that is closest to the target
 as the next best tile.

Author:

Kevin Glass

Constructor Summary

AStarHeuristic()

Method Summary

 float
getCost(Map map,
        Actor mover,
        int x,
        int y,
        int tx,
        int ty)

          Get the additional heuristic cost of the given tile.

Methods inherited from class java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructor Detail

AStarHeuristic

public AStarHeuristic()

Method Detail

getCost

public float getCost(Map map,
                     Actor mover,
                     int x,
                     int y,
                     int tx,
                     int ty)

Get the additional heuristic cost of the given tile. This controls the
 order in which tiles are searched while attempting to find a path to the
 target location. The lower the cost the more likely the tile will
 be searched.

Parameters:
map - The map on which the path is being found
mover - The entity that is moving along the path
x - The x coordinate of the tile being evaluated
y - The y coordinate of the tile being evaluated
tx - The x coordinate of the target location
ty - Teh y coordinate of the target location

Returns:
The cost associated with the given tile

      Package
    Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

  All Classes

  SUMMARY: NESTED | FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD


text:
This sample creates a sketch tool that creates multiple features in 3D. It demonstrates a line sketch tool, working with 3D geometry, and edit templates.

View it live

```
Language:      C#
Subject:       Editing
Contributor:   ArcGIS Pro SDK Team <arcgisprosdk@esri.com>
Organization:  Esri, http://www.esri.com
Date:          9/3/2015
ArcGIS Pro:    1.1
Visual Studio: 2013, 2015
```

##Resources

* [API Reference online](http://pro.arcgis.com/en/pro-app/sdk/api-reference)
* ArcGIS Pro SDK for .NET (pro.arcgis.com)
* [arcgis-pro-sdk-community-samples](http://github.com/Esri/arcgis-pro-sdk-community-samples)
* [FAQ](http://github.com/Esri/arcgis-pro-sdk/wiki/FAQ)
* [ArcGIS Pro SDK icons](https://github.com/Esri/arcgis-pro-sdk/releases/tag/1.1.0.3308)
* [ProConcepts: ArcGIS Pro Add in Samples](https://github.com/Esri/arcgis-pro-sdk-community-samples/wiki/ProConcepts-ArcGIS-Pro-Add-in-Samples)

##How to use the sample

1. The sample was initially created for internal demonstrations to show feature construction in 3D.
1. It requires the main (line), connector (line) and manhole (point) 3D layers in a scene.
1. The demonstration shows using the sketch to draw on a surface with the resulting features created underneath and connecting.
![UI](Screenshots/Screen.png)
1. The following two screenshots are examples of the expected output.
![UI](Screenshots/OutputExample1.png)
![UI](Screenshots/OutputExample2.png)

[](Esri Tags: ArcGIS-Pro-SDK)
[](Esri Language: C-Sharp)

 ArcGIS Pro 1.1 SDK for Microsoft .NET Framework

                    [Home](https://github.com/Esri/arcgis-pro-sdk/wiki) | ArcGIS Pro SDK | API Reference | [Requirements](#requirements) | [Download](#download) |  Samples


text:
layout: post
title:  Git fundamentals - branch, fork, stash, merge, rebate, squash
author: Andy Feng
---

This article introduces Git fundamental knowledge including branch, fork, stash, merge, rebate. It explains major conceptions of Git branching model and workflow for each commands.  These commands are required for next posting - best practice for team development via Git.

## Outline ##

1. Basic commands review
	- set up git
	- create local repository
	- stage file(s)
	- commit file(s)
	- sync remote repository and local repository
	- display git information
	- discard changes

1. Branch
	- Introduction
	- Workflow

1. Fork
	- Introduction
	- Workflow
	- fork vs clone
	- fork vs branch

1. Stash
	- Introduction
	- Workflow

1. Merge, Rebate, Squash

## Basic commands review ##

This is the git model:

![](/images/posts/20171109-git-34.png)

**Remote** represents the remote repository

**Repository** is the local repository

**workspace** is the active branch we currently working on

**Index** is the staging area

Here are some basic Git commands:

### Setup git ###

**display git configuration**

`git config --list`

**edit git configuration**

`git config -e [--global]`

**setup user commit information**

`git config [--global] user.name "Andy Feng"`

`git config [--global] user.email "andy@email.com"`

### Create local git repository ###

**Setup new git repository**

`mkdir new-repository`

`cd new-repository`

`git init`

`touch readme`

`git add readme`

`git commit -m "first commit"`

`git remote add origin https://github.com/new-repository.git`
> origin is an alias of remote repository.

`git push -u origin master`
> master is the name of main branch in local repository
> it is equivalent to `git push -u origin/master master`

**Setup existing git repository**

`cd existing-repository`

`git remote add origin https://github.com/existing-repository.git`

`git push -u origin master`

**Clone a remote repository**

`git clone https://github.com/existing-repository.git`

**Create upstream tracking between remote branch and local branch**

`git branch --set-upstream-to origin/master master`

### Stage files to Index ###

**stage specified files**

`git add [file1] [file2]...`

**stage specified directory**

`git add [dir]`

**stage all files **

`git add .`

`git add -A`

**delete specified files and stage them**

`git rm [file1] [file2]...`

### Commit files to local repository ###

**commit all staged files to local repository**

`git commit -m [message]`

**commit specified staged files to local repository**

`git commit [file1] [file2] ... -m [message]`

**display all diff information of commits**

`git commit -v`

### Sync remote repository and local repository ###

**Pull all remote changes**

`git fetch origin`
> origin is the name of remote repository. As a convention, we usually name it as `origin`

**Pull all remote changes and merge into a local branch**

`git pull <remote-branch> <local-branch>`

e.g. `git pull origin master`

**Push changes of a local branch to remote repository**

`git push <remote-branch> <local-branch>`

**Push all local branches to remote repository**

`git push <remote-branch> --all`

### Display git information ###

**Display all changed files before commit to local repository**

`git status`

**Display the difference between workplace and Index**

`git diff`

** List git commits **

Get the commit history of current branch

`git log`

Get the commit history of recent n commits

`git log -n`

Get the commit history and all files of current branch

`git log --state`

search git commits

`git log -S <keyword>`

**Display the changed content of commit**

`git show`

`git show <commit>`
> display a specified commit

**Display all configured remote repositories**

`git remote -v`

### Discard changes ###

**Restore files to Workspace**

Restore specified file from staged area (Index)

`git checkout <file>`

Restore all files from staged area

`git checkout .`

Restore from committed files

`git checkout <commit> <file>`

> restore operation still keeps the staged or committed files. But the same files will be overwritten by the restored ones and new changes of files will lose. Status of file is not changed for this operation.

**Reset files from commits**

Reset specified file from local repository to staged area (Index) until last commit

`git reset <committed-file>`

Reset from local repository to staged area until specified comit

`git reset <commit>`

Reset both staged area and workspace until last commit, all changes in workspace lost

`git reset --hard`

Reset both staged area and workspace until specified commit, all changes in workspace lost

`git reset --hard <commit>`

Reset to specified commit, and create a new commit for this reset

`git revert <commit>`

Reset to specified commit, and keep all changes in workspace

`git reset --keep <commit>`

> reset operation essentially rollbacks files from previous commit status.
> by default, only the status of file is changed from committed to staged. New changes of files still keep.
> --hard option: both the status of file is reset and the changes of file lose
> --keep option: only reset the status of file but keep the changes of file

e.g. discard all local changes and reset master branch:

switch the repo to the master branch: `git checkout master`

pull the latest commits: `git fetch origin`

reset the repo's local copy of master branch to match the latest version: `git reset --hard origin/master`

## Branch ##
### Introduction ###
A branch represents an independent line of development. When a git repository is created, a default master branch is created. We can create new branches anytime.

In Git, branch is a part of our everyday development process. When we want to add a new feature or fix a bug — no matter how big or how small — we spawn a new dedicated branch to encapsulate our changes. Then, we clean up the feature's history before merging it into the main branch.

The benefit is, branch makes sure that unstable code is never committed to the main code base and keep development activities organized.

![](/images/posts/20171109-git-1.png)

For example, the diagram above visualizes a repository with two isolated lines of development, one for a little feature, and one for a big feature. By developing them in branches, it's not only possible to work on both of them in parallel, but it also keeps the main master branch free from questionable code.

Here are some common commands:

**List all branches in local repository**

`git branch`

**List all branches in remote repository**

`git branch -r`

**List all local and remote branches **

`git branch -a`

**Create a new branch called <branch>. This does not check out the new branch.**

`git branch <new-branch>`

**Switch to another branch**

`git checkout <existing-branch>`

**Create and switch to another branch**

`git checkout -b <new-branch>`

> -b flag tells Git to create the branch if it doesn't already exist.

**Delete a branch**

`git branch -d <branch>`

> This is a "safe" operation in that Git prevents you from deleting the branch if it has unmerged changes.

`git branch -D <branch>`

> This is a "force" delete operation and it will permanently delete the specified branch, even if it has unmerged changes.

**Rename the current branch to another name <new-branch>.**

`git branch -m <new-branch>`

**push a branch to remote server**

push a branch to remote server

`git push origin <branch>`

push "master" branch to remote server

`git push origin master`

**delete a remote branch**

`git push origin --delete [branch-name]`

### Workflow ###

Here is how Git branching model works:

1. create a new branch for each new feature/fix

	`git checkout -b <new-branch>`

1. work on it

1. merge it back to Master when done

	`git checkout master`

	`git merge <branch>`

	fix conflicts if has any

	`git commit`

	or

	`git merge <branch> master`

1. push master branch to remote repository

	`git push origin master`

1. delete the feature branch

	`git branch -d <branch>`

## Fork ##
### Introduction ###
Fork represents a complete copy of a repository. It creates a complete server-side repository copied from the original repository and allows us to freely experiment with changes without affecting the original project.

There are tons of public repositories over Internet. Usually, we are not the direct contributors. Fork offers an opportunity for us to engage in contribution. Fork allows us to clone these public repositories and create our own server-side repositories from them. Then, we can work on forked repositories exactly like we contribute our own repositories. Later on, we can initiate pull requests to original repositories and notify the owners to accept our contributions. Overall, fork allows the maintainer to accept commits from any developer without giving them write access to the official codebase.

![](/images/posts/20171109-git-2.png)

In forking workflow, the original repository is typically named **upstream** and runs independently. The forked repository (typically named **origin**) and local cloned copy is runs independently too.

Here are some common commands:

**clone a fork**

`git clone https://user@bitbucket.org/user/official-repo.git`

However, this command has to be executed in the developer's server side or via Github/Bitbucket's API on command line.

Usually, we make a fork via the fork button of the project and it is quicker and easier

![](/images/posts/20171109-git-3.png)

**add remote upstream point**

`git remote add upstream https://bitbucket.org/maintainer/official-repo`

> Whereas a regular Git workflow uses a single **origin** remote that points to the central repository, the Forking Workflow requires two remotes — one for the official repository(typically called **upstream**), and one for the developer's personal server-side repository(typically called **origin**).

if our upstream repository has authentication enabled (i.e., it's not open source), we will need to supply a username

`git remote add upstream https://user@bitbucket.org/maintainer/official-repo.git`

This requires users to supply a valid password before cloning or pulling from the official codebase.

**making & pushing changes**

In the developer's local copy of the forked repository we can edit code, commit changes, and create branches just like in usual Git workflows:

create a new branch: `git checkout -b some-feature`

edit some code: `git commit -a -m "Add first draft of some feature"`

push to forked repository: `git push origin`

**Grab new updates from official repo**

`git pull upstream master`

**make a pull request**
Once a developer is ready to share a new feature, we need to do two things.

1. First, we have to make the contribution accessible to other developers by pushing it to their public repository: `git push origin feature-branch`

	This merges changes in the origin remote points to the developer's personal server-side repository, not the main codebase.

1. Next, we need to notify the "official" project maintainer that we want to merge the new feature into the main codebase. We can do this by the "pull request" button and it leads us to a form asking you to specify which branch you want to merge into the official repository. Typically, we want to integrate your feature branch into the upstream remote's master branch.

	![](/images/posts/20171109-git-8.png)

> If I am in a branch of a project, after I made some changes. I send a pull request to the project owner. He receive the pull request and merge my code. Pull request works like an alert to notify the owner it is okay to merge. If I do not send pull request, he can also merge my code.

### Workflow ###
Here is how it works:

1. There is an official public repository stored on a server and a new developer wants to start working on the project.

	`https://github.com/i0natan/nodebestpractices`

1. A developer **"forks"** this official server-side repository. This creates their own server-side copy.

	![](/images/posts/20171109-git-3.png)

	![](/images/posts/20171109-git-4.png)

	![](/images/posts/20171109-git-5.png)

	After fork, we have our own repository `https://github.com/myusername/nodebestpractices`

1. The developer clones the new server-side copy to their local system.

	`git clone https://github.com/myusername/nodebestpractices`

	![](/images/posts/20171109-git-6.png)

1. A Git remote path for the "official" repository is added to the local clone. It is a link with the original repo and called **upstream**.

	`git remote add upstream https://github.com/i0natan/nodebestpractices`

1. The developer makes changes on the forked repository as usual.

1. The developer creates new commits for the changes.

1. New changes are pushed to the developer's own server-side copy.

	![](/images/posts/20171109-git-7.png)

1. The developer opens a **pull request** from the new branch to the "official" repository.

	![](/images/posts/20171109-git-8.png)

	![](/images/posts/20171109-git-9.png)

	Select the desired forked/upstream branches at the top, enter message and submit the pull request

	![](/images/posts/20171109-git-10.png)

1. The pull request gets approved for merge and is merged into the original server-side repository.

1. The contribution is now part of the project, and other developers pull from the official repository to synchronize their local repositories.

1. The developer constantly grab new updates from "official" repository in order to keep synchronizing with it.

	`git pull upstream master`

	![](/images/posts/20171109-git-11.png)

### fork vs clone ###
> - Forked repositories can be regarded as "server-side clones" and usually managed and hosted by a 3rd party Git service like Github, Bitbucket.
> - A "fork" is a "clone" from official repository to remote repository. It happens in server sides.
> - A typical "clone" operation is essentially a copy from a remote repository to local repository. It happens from server side from local side.

### fork vs branch  ###
> - Fork is just another way to share branches between repositories with other developers
> - Developers should still use branches to isolate individual features to their own local and remote repositories
> - The major difference is how those branches get shared. In the forking workflow, branches are shared between maintainer's official repository and another developer's remote repository. In the branching Workflow, branches are shared between one developer's repositories.

### summary ###
Generally, forks are used to either propose changes to someone else's project or to use someone else's project as a starting point for your own idea. The Forking Workflow is commonly used in public open-source projects. Forking is a git clone operation executed on a server copy of a projects repo. A Forking Workflow is often used in conjunction with a Git hosting service like Github/Bitbucket.

A brief steps of Forking Workflow is:

1. We want to contribute to an open source library

1. We create a **fork** of the repo via a Git hosting service i.e. Github, Bitbucket

1. We use git **clone** to get a local copy of the forked repo

1. We create a new feature **branch** in your local repo then work on it

1. Work is done to complete the new feature and git **commit** is executed to save the changes

1. We then **push** the new feature branch to our remote forked repo

1. We use Git hosting service to open up a **pull request** for the new branch against the original repo

## Stash ##
### introduction ###

`Stash` temporarily store changes we have made to your working copy so we can work on something else, and then come back and re-apply these changes later on. stash is a great feature for us to work on multiple branches.

#### Problem ####

Typically, we create a new branch for each new requirement. After development work is done, we merge the changes back to trunk branch. However, we sometimes have to create new branch or switch to another branch for new urgent tasks before the work of current branch is completed.

There are some issues for that:

1. don't commit changes -
	1. Case 1: If we switch to another branch with uncommited changes of new added files in current branch, these uncommited changes will also be carried to the new branch that you switch to. Changes that our next commit will be commited to the newly switched branch.
	2. Case 2: If we try to switch to another branch with updated files and we already got another branch updated same files, Git doesn't allow us to switch between branches. The reason is Git finds a conflict between the files from the newly switched branch and the uncommited changes from the current branch. Therefore, we are required to commit or stash changes first before switching branch.

		e.g. We have "stash2.txt" commited new changes in master branch. Also, we currently in develop branch and got "stash2.txt" updated. We cannot switch back to master branch.

		![](/images/posts/20171109-git-23.png)

1. commit changes - If we commit uncompleted changes in current branch, then create new branch and start working on, we might include broken code in current branch.

Obviously, we should always keep changes within current branch and find a good way to cache changes if we prefer not to commit dirty changes when switching branches.

#### Solution ####

Stash is a solution for that. Stashing likes a a drawer to store uncommited changes temporarily. It allows us to put aside the dirty changes in your working tree and continue working on other things in a different branch on a clean slate.

Uncommited changes that are stored in the stash can be taken out and applied to the original branch and other branches as well. It helps us to cache changes and kind of "revert" changes to last commit of current branch. Then we can switch branches safely.

![](/images/posts/20171109-git-24.png)

### workflow ###

1. we are working on one branch(develop) and updated "stash2.txt" file

1. we got "stash2.txt" commited changes in another branch(master)

1. For some reason, we have to create or switch new branch. We prefer not to commit "stash2.txt" file and choose to stash it.

1. stash our changes

	`git stash`

	Current branch will revert to last commit.

1. Display stash list:

	`git stash list`

1. switch to new branch, do some work

	`git checkout -b <another-branch>`

1. pop out changes from git cache. Git will append changes for same files.

	`git stash pop`

	With this command, it deletes that stash. Please note that the stash is shared within all branches. Which branch we are currently on, the changes will be popped to that branch.

1. Solve conflicts issue if has any. commit and merge changes to trunk branch

	![](/images/posts/20171109-git-26.png)

Other commands:

Apply most recent stashing without removing

	`git stash apply`

	apply specified stashing

	`git stash apply stash@{stashing_index}`

Remove most recent stashing

	`git stash drop`

	remove specified stashing

	`git stash drop stash@{0}`

Clean out the stashing stack

	`git stash clear`

## Merge, Rebase, Squash ##

In Git, there are two main ways to integrate changes from one branch into another: the merge and the rebase.

### Merge ###

merge is the easiest option to merge changes within branches

**merge another branch into current branch**

`git merge <another-branch>`

`git merge --no-ff <branch>`
> Merge the specified branch into the current branch, but always generate a merge commit (even if it was a fast-forward merge). This is useful for documenting all merges.

e.g. We have a feature branch and hope to merge changes to master branch:

`git checkout master`
`git merge feature`

Or, we can condense this to a one line:

`git merge master feature`

This creates a new "merge commit" in the feature branch that ties together the histories of both branches, giving us a branch structure that looks like this:

![](/images/posts/20171109-git-27.png)

However, each `merge` generates a certain merge point when we incorporate changes. If we have many branches and merge happens very often, this can pollute our master branch's history quite a bit.

![](/images/posts/20171109-git-28.png)

`git checkout feature`
`git rebase master`

### Rebase ###

As an alternative to merging, we rebase the feature branch onto master branch using the following commands:

`git checkout master`
`git rebase feature`

This moves the entire feature branch to begin on the tip of the master branch by incorporating all of the new commits in master. Instead of creating a merge commit point, rebasing re-writes the project history by creating brand new commits for each commit in the original branch and fast-forwards the commit. Rebasing is essentially fast-forward merge.

![](/images/posts/20171109-git-29.png)

The major benefit of rebasing is that you get a much cleaner project history. It eliminates the unnecessary merge commits created by git merge. However, we lost the context provided by merge commit.

In practice, if our team members pushed changes prior you in remote branch. We have to use `git pull` to grab those changes. By default, git use `merge` option to incorporate changes. In this case, a new merge commit point will be created. We can use `rebase` option to fast forward to new changes:

`git pull --rebase`

In most cases, we choose `rebase` policy for a clearer git history for code review.

### Squash ###
Squash option can produce a "squashed" commit. It compress multiple commits into one single commit and simplify git history. Squash is not a command but an option and it is used together with merge or rebate.

#### Merge + Squash ####

e.g. we squash all commits of feature branch and merge to master branch

`git checkout master`
`git merge --squash`

After squash, there is only one commit from feature branch merged to master branch

#### rebase + squash/fixup ####

e.g. we hope to merge git log

	a
	b1
	b2
	b3

to

	a
	b

1. check commit history via `git log`

1. enable rebate interactive editing

	`git rebase -i <SHA-1 of commit a>

1. edit the instructions to modify b2, b3 from "pick" to "squash"

	- pick: commit
	- squash: meld into previous commit

	modify

	![](/images/posts/20171109-git-31.png)

	to

	![](/images/posts/20171109-git-32.png)

	esc > :wq > save and exit

1. enter new commit message

	![](/images/posts/20171109-git-33.png)

Here is the complete commands

	![](/images/posts/20171109-git-30.png)

After squash, the rebate will only keep one commit. Basically, squash option let us to squash commits backwards until recent "pick".

fixup option like squash, the only difference is squash keeps all commits' messages but fixup discard all previous commits' messages.

## References ##

[Forking Workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/forking-workflow)

[Git stash tutorial](https://www.atlassian.com/git/tutorials/git-stash)

[Merging vs. Rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)

[Understanding the GitHub Flow](https://guides.github.com/introduction/flow/index.html)


text:
class User < ActiveRecord::Base
  has_many :reviews, :dependent => :destroy, :foreign_key=> "reviewee_id"
  has_many :vehicles, :dependent => :destroy
  has_many :rides, :dependent => :destroy, :foreign_key => "driver_id", :conditions => ["rides.starttime > ?", Time.zone.now]
  has_many :recieved_messages, :class_name => "Mthread", :foreign_key => "recipient_id"

  validates_presence_of :firstname

  has_attached_file :avatar, :styles => { :medium => "150x150#", :thumb => "50x50#" }, :default_url => '/assets/missing_:style.jpg'
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable,
         :validatable, :omniauthable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me, :firstname, :lastname, :birthday, :music, :talking, :pets, :smoking, :detour, :phone, :bio, :experience, :role, :avatar, :hidephone, :hideemail

  def age
    if birthday
      age = Date.today.year - birthday.year
      if Date.today < birthday + age.years
        age -= 1
      else
        age
      end
    else
      age = nil
    end
  end

  def messages
    Mthread.where("recipient_id = #{id} OR sender_id = #{id}")
  end

  def unread_messages
    Mthread.find(:all, :conditions => [ "(recipient_id = #{id} AND recipient_read  = ?) OR (sender_id = #{id} AND sender_read=?)", false, false])
  end

  def name
    name = firstname
    if lastname
      name += ' ' + lastname[0...1] + '.'
    else
      name
    end
  end

  def review_percent
    total_reviews = Review.where("reviewee_id=?", id).length
    positive_reviews = Review.where("reviewee_id=? AND positive=?", id, true).length
    if not positive_reviews.zero?
      (positive_reviews.to_f/total_reviews.to_f*100).to_i
    else
      positive_reviews
    end
  end

  def review_stars
    stars = (review_percent().to_f/20.to_f).to_i
    rp = review_percent()/10
    if rp<9 and rp.odd?
      stars+1
    else
      stars
    end

  end

  def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
    data = access_token['extra']['user_hash']
    if user = User.find_by_email(data["email"])
      user
    else # Create a user with a stub password.
      User.create(:email => data["email"], :firstname => data["first_name"], :lastname => data["last_name"], :password => Devise.friendly_token[0,20])
    end
  end

  def self.new_with_session(params, session)
    super.tap do |user|
      if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["user_hash"]
        user.email = data["email"]
      end
    end
  end

end


text:
package com.nestedworld.nestedworld.data.network.socket.models.request.combat;

import android.support.annotation.NonNull;

import com.nestedworld.nestedworld.data.network.socket.models.request.DefaultRequest;

import org.msgpack.value.ValueFactory;

public class ReplaceMonsterRequest implements DefaultRequest {

    private final long userMonsterId;
    private final long combatId;

    /*
    ** Constructor
     */
    public ReplaceMonsterRequest(final long userMonsterId, final long combatId) {
        this.userMonsterId = userMonsterId;
        this.combatId = combatId;
    }

    /*
    ** DefaultRequest implementation
     */
    @NonNull
    @Override
    public ValueFactory.MapBuilder serialise() {
        ValueFactory.MapBuilder mapBuilder = ValueFactory.newMapBuilder();
        mapBuilder.put(ValueFactory.newString("combat"), ValueFactory.newInteger(combatId));
        mapBuilder.put(ValueFactory.newString("user_monster_id"), ValueFactory.newInteger(userMonsterId));
        return mapBuilder;
    }
}


text:
<?php

namespace Mage\Checkout\Test\Block\Multishipping;

use Magento\Mtf\Block\Block;
use Magento\Mtf\Client\ElementInterface;
use Mage\Checkout\Test\Block\Multishipping\Shipping\Items as ShippingItems;
use Mage\Checkout\Test\Block\Multishipping\Addresses\Items as AddressItems;

/**
 * Checkout multishipping abstract block.
 */
abstract class AbstractMultishipping extends Block
{
    /**
     * Selector for 'Continue' button.
     *
     * @var string
     */
    protected $continue;

    /**
     * Get path for items class.
     *
     * @return string
     */
    protected abstract function getItemsClass();

    /**
     * Get items block element.
     *
     * @return ElementInterface
     */
    protected abstract function getItemsBlockElement();

    /**
     * Get items block.
     *
     * @return ShippingItems|AddressItems
     */
    public function getItemsBlock()
    {
        return $this->blockFactory->create($this->getItemsClass(), ['element' => $this->getItemsBlockElement()]);
    }

    /**
     * Click on 'Continue' button.
     *
     * @return void
     */
    public function clickContinueButton()
    {
        $this->_rootElement->find($this->continue)->click();
    }
}


text:
package org.wso2.iot.firealarm.access;

import org.wso2.iot.firealarm.access.api.FirealarmClient;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class OperationServlet extends HttpServlet {
	protected void doPost(HttpServletRequest request,
	                      HttpServletResponse response)
			throws ServletException, IOException {

		String token = (String) request.getSession(true).getAttribute("token");
		request.setAttribute("errMsg", null);
		if (token == null) {
			request.setAttribute("errMsg", "Invalid Credential / Unauthorized Access");

			request.getRequestDispatcher("index.jsp").forward(request, response);
		}

		String operation = request.getParameter("operation");
		String protocol = request.getParameter("protocol");
		String username = (String) request.getSession(true).getAttribute("username");

		if (operation.equals("bulb")) {
			String deviceId = request.getParameter("deviceId");
			String state = request.getParameter("state");
			FirealarmClient fc = new FirealarmClient();
			String resp = fc.switchBulb(token, username, deviceId, state, protocol);
			response.getWriter().print(resp);
		} else if (operation.equals("temp")) {
			String deviceId = request.getParameter("deviceId");
			FirealarmClient fc = new FirealarmClient();
			String temperature = fc.getTemperature(token, username, deviceId, protocol);
			if (temperature != null) {
//				request.setAttribute("tempReply",temperature);
//				request.getRequestDispatcher("control.jsp").forward(request,response);
				try {
					response.getWriter().print("Temperature is " + Double.parseDouble
							(temperature) +

							                           " C");
				} catch (NumberFormatException e) {

					response.getWriter().print(temperature);
				}
			} else {
//				request.setAttribute("errMsg","Connection Failed try again later");
//				request.setAttribute("tempReply",null);
//				request.getRequestDispatcher("control.jsp").forward(request,response);
				response.getWriter().print("Connection Failure,Try again later");
			}
		} else if (operation.equals("humid")) {
			String deviceId = request.getParameter("deviceId");
			FirealarmClient fc = new FirealarmClient();
			String humidity = fc.getHumidity(token, username, deviceId, protocol);
			if (humidity != null) {
//				request.setAttribute("tempReply",temperature);
//				request.getRequestDispatcher("control.jsp").forward(request,response);
				try {
					response.getWriter().print("Humidity is " + Double.parseDouble(humidity) +

							                           "%");
				} catch (NumberFormatException e) {

					response.getWriter().print(humidity);
				}
			} else {
//				request.setAttribute("errMsg","Connection Failed try again later");
//				request.setAttribute("tempReply",null);
//				request.getRequestDispatcher("control.jsp").forward(request,response);
				response.getWriter().print("Connection Failure,Try again later");
			}
		}

	}

	protected void doGet(HttpServletRequest request,
	                     HttpServletResponse response)
			throws ServletException, IOException {

		String token = (String) request.getSession(true).getAttribute("token");
		request.setAttribute("errMsg", null);
		if (token == null) {
			request.setAttribute("errMsg", "Invalid Credential / Unauthorized Access");

			request.getRequestDispatcher("index.jsp").forward(request, response);
		}
		request.getRequestDispatcher("control.jsp").forward(request, response);

	}
}


text:
#ifndef MMF2EXTDOC_H
#define MMF2EXTDOC_H

#include <QtGui/QDialog>
namespace Ui { class MMF2ExtDocClass; }
class MF2Description;

class MMF2ExtDoc : public QDialog
{
	Q_OBJECT

public:
	MMF2ExtDoc(QWidget *parent = 0, Qt::WFlags flags = 0);
	~MMF2ExtDoc();

protected slots:
	void loadFile();
	void saveFile();
	void importExtension();
	void showPage(const QModelIndex &);
	void updatePageText();
	void editParams();
	void insertPage();
	void appendPage();
	void deletePage();
	void resetModel();
	void setExtensionName(QString);

private:
	Ui::MMF2ExtDocClass *ui;
	QString m_lastOpenedFile;
	MF2Description *m_data;
};

#endif // MMF2EXTDOC_H


text:
package krusty_test

import (
	"testing"

	"github.com/stretchr/testify/assert"

	kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)

func TestPatchesInOneFile(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK("base", `
resources:
- namespace.yaml
- deployment-controller-manager.yaml
- deployment-audit-manager.yaml
`)
	th.WriteF("base/namespace.yaml", `
apiVersion: v1
kind: Namespace
metadata:
  labels:
    control-plane: controller-manager
    admission.gatekeeper.sh/ignore: no-self-managing
  name: system
`)
	th.WriteF("base/deployment-controller-manager.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: controller-manager
  namespace: system
  labels:
    control-plane: controller-manager
    gatekeeper.sh/operation: webhook
spec:
  selector:
    matchLabels:
      control-plane: controller-manager
      gatekeeper.sh/operation: webhook
  replicas: 3
  template:
    metadata:
      annotations:
        container.seccomp.security.alpha.kubernetes.io/manager: runtime/default
      labels:
        control-plane: controller-manager
        gatekeeper.sh/operation: webhook
    spec:
      containers:
        - command:
            - /manager
          args:
            - "--port=8443"
            - "--logtostderr"
            - "--exempt-namespace=gatekeeper-system"
            - "--operation=webhook"
          image: openpolicyagent/gatekeeper:v3.4.0
          imagePullPolicy: Always
          name: manager
      terminationGracePeriodSeconds: 60
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
`)
	th.WriteF("base/deployment-audit-manager.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: audit
  namespace: system
  labels:
    control-plane: audit-controller
    gatekeeper.sh/operation: audit
spec:
  selector:
    matchLabels:
      control-plane: audit-controller
      gatekeeper.sh/operation: audit
  replicas: 1
  template:
    metadata:
      labels:
        control-plane: audit-controller
        gatekeeper.sh/operation: audit
      annotations:
        container.seccomp.security.alpha.kubernetes.io/manager: runtime/default
    spec:
      automountServiceAccountToken: true
      containers:
        - args:
            - --operation=audit
            - --operation=status
            - --logtostderr
          command:
            - /manager
          env:
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          image: openpolicyagent/gatekeeper:v3.4.0
          imagePullPolicy: Always
          livenessProbe:
            httpGet:
              path: /healthz
              port: 9090
          name: manager
      serviceAccountName: gatekeeper-admin
      terminationGracePeriodSeconds: 60
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
`)
	const imagePatchAuditManager = `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: audit
  namespace: system
spec:
  template:
    spec:
      containers:
      - image: AUDIT_IMAGE
        name: manager
        args:
        - --port=8443
        - --logtostderr
        - --emit-admission-events
        - --exempt-namespace=gatekeeper-system
        - --operation=webhook
        - --disable-opa-builtin=http.send
`
	const imagePatchControllerManager = `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: controller-manager
  namespace: system
spec:
  template:
    spec:
      containers:
      - image: CONTROLLER_IMAGE
        name: manager
        args:
        - --emit-audit-events
        - --operation=audit
        - --operation=status
        - --logtostderr
`
	th.WriteF(
		"overlay/image_patch_audit_manager.yaml",
		imagePatchAuditManager)
	th.WriteF(
		"overlay/image_patch_controller_manager.yaml",
		imagePatchControllerManager)
	const expected = `
apiVersion: v1
kind: Namespace
metadata:
  labels:
    admission.gatekeeper.sh/ignore: no-self-managing
    control-plane: controller-manager
  name: system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    control-plane: controller-manager
    gatekeeper.sh/operation: webhook
  name: controller-manager
  namespace: system
spec:
  replicas: 3
  selector:
    matchLabels:
      control-plane: controller-manager
      gatekeeper.sh/operation: webhook
  template:
    metadata:
      annotations:
        container.seccomp.security.alpha.kubernetes.io/manager: runtime/default
      labels:
        control-plane: controller-manager
        gatekeeper.sh/operation: webhook
    spec:
      containers:
      - args:
        - --emit-audit-events
        - --operation=audit
        - --operation=status
        - --logtostderr
        command:
        - /manager
        image: CONTROLLER_IMAGE
        imagePullPolicy: Always
        name: manager
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
      terminationGracePeriodSeconds: 60
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    control-plane: audit-controller
    gatekeeper.sh/operation: audit
  name: audit
  namespace: system
spec:
  replicas: 1
  selector:
    matchLabels:
      control-plane: audit-controller
      gatekeeper.sh/operation: audit
  template:
    metadata:
      annotations:
        container.seccomp.security.alpha.kubernetes.io/manager: runtime/default
      labels:
        control-plane: audit-controller
        gatekeeper.sh/operation: audit
    spec:
      automountServiceAccountToken: true
      containers:
      - args:
        - --port=8443
        - --logtostderr
        - --emit-admission-events
        - --exempt-namespace=gatekeeper-system
        - --operation=webhook
        - --disable-opa-builtin=http.send
        command:
        - /manager
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        image: AUDIT_IMAGE
        imagePullPolicy: Always
        livenessProbe:
          httpGet:
            path: /healthz
            port: 9090
        name: manager
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
      serviceAccountName: gatekeeper-admin
      terminationGracePeriodSeconds: 60
`
	// Technique 1: "patchesStrategicMerge:" field, two patch files.
	th.WriteK("overlay", `
resources:
- ../base
patchesStrategicMerge:
- image_patch_controller_manager.yaml
- image_patch_audit_manager.yaml
`)
	m := th.Run("overlay", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, expected)

	// Technique 2: "patches:" field, two patch files.
	th.WriteK("overlay", `
resources:
- ../base
patches:
- path: image_patch_controller_manager.yaml
- path: image_patch_audit_manager.yaml
`)
	m = th.Run("overlay", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, expected)

	// Technique 3: "patchesStrategicMerge:" field, one patch file.
	th.WriteK("overlay", `
resources:
- ../base
patchesStrategicMerge:
- twoPatchesInOneFile.yaml
`)
	th.WriteF(
		"overlay/twoPatchesInOneFile.yaml",
		imagePatchAuditManager+"\n---\n"+imagePatchControllerManager)
	m = th.Run("overlay", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, expected)

	// Technique 4: "patches:" field, one patch file.  Fails.
	th.WriteK("overlay", `
resources:
- ../base
patches:
- path: twoPatchesInOneFile.yaml
`)
	err := th.RunWithErr("overlay", th.MakeDefaultOptions())
	assert.Error(t, err)
	// This should fail, because the semantics of the `patches` field.
	// That field allows specific patch targeting to a list of targets,
	// while the `patchesStrategicMerge` field accepts patches that
	// implicitly identify their targets via GVKN.
	assert.Contains(t, err.Error(), "unable to parse SM or JSON patch from ")
}

func TestRemoveEmptyDirWithNullFieldInSmp(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK(".", `
resources:
- deployment.yaml
patchesStrategicMerge:
- patch.yaml
`)
	th.WriteF("deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      volumes:
      - name: fancyDisk
        emptyDir: {}
`)
	th.WriteF("patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      volumes:
      - name: fancyDisk
        emptyDir: null
`)
	m := th.Run(".", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      volumes:
      - name: fancyDisk
`)
}

func TestRemoveEmptyDirAddPersistentDisk(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK(".", `
resources:
- deployment.yaml
patchesStrategicMerge:
- patch.yaml
`)
	th.WriteF("deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      volumes:
      - name: fancyDisk
        emptyDir: {}
`)
	th.WriteF("patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      volumes:
      - name: fancyDisk
        emptyDir: null
        gcePersistentDisk:
          pdName: fancyDisk
`)
	m := th.Run(".", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      volumes:
      - gcePersistentDisk:
          pdName: fancyDisk
        name: fancyDisk
`)
}

func TestVolumeRemoveEmptyDirInOverlay(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK("base", `
resources:
- deployment.yaml
configMapGenerator:
- name: baseCm
  literals:
  - foo=bar
`)
	th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: fancyDisk
          mountPath: /tmp/ps
      volumes:
      - name: fancyDisk
        emptyDir: {}
      - configMap:
          name: baseCm
        name: baseCm
`)
	m := th.Run("base", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - mountPath: /tmp/ps
          name: fancyDisk
      volumes:
      - emptyDir: {}
        name: fancyDisk
      - configMap:
          name: baseCm-798k5k7g9f
        name: baseCm
---
apiVersion: v1
data:
  foo: bar
kind: ConfigMap
metadata:
  name: baseCm-798k5k7g9f
`)

	th.WriteK("overlay", `
patchesStrategicMerge:
- patch.yaml
resources:
- ../base
configMapGenerator:
- name: overlayCm
  literals:
  - hello=world
`)
	th.WriteF("overlay/patch.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      volumes:
      - name: fancyDisk
        emptyDir: null
        gcePersistentDisk:
          pdName: fancyDisk
      - configMap:
          name: overlayCm
        name: overlayCm
`)
	m = th.Run("overlay", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - mountPath: /tmp/ps
          name: fancyDisk
      volumes:
      - gcePersistentDisk:
          pdName: fancyDisk
        name: fancyDisk
      - configMap:
          name: overlayCm-dc6fm46dhm
        name: overlayCm
      - configMap:
          name: baseCm-798k5k7g9f
        name: baseCm
---
apiVersion: v1
data:
  foo: bar
kind: ConfigMap
metadata:
  name: baseCm-798k5k7g9f
---
apiVersion: v1
data:
  hello: world
kind: ConfigMap
metadata:
  name: overlayCm-dc6fm46dhm
`)
}

// Goal is to remove "  emptyDir: {}" with a patch.
func TestRemoveEmptyDirWithPatchesAtSameLevel(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK("base", `
resources:
- deployment.yaml
`)
	th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx
      - name: sidecar
        image: sidecar:latest
      volumes:
      - name: nginx-persistent-storage
        emptyDir: {}
`)
	th.WriteK("overlay", `
patchesStrategicMerge:
- deployment-patch1.yaml
- deployment-patch2.yaml
resources:
- ../base
`)
	th.WriteF("overlay/deployment-patch1.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      volumes:
      - name: nginx-persistent-storage
        emptyDir: null
        gcePersistentDisk:
          pdName: nginx-persistent-storage
`)
	th.WriteF("overlay/deployment-patch2.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - image: nginx
        name: nginx
        env:
        - name: ANOTHERENV
          value: FOO
      volumes:
      - name: nginx-persistent-storage
`)
	opts := th.MakeDefaultOptions()
	m := th.Run("overlay", opts)
	th.AssertActualEqualsExpected(
		m, `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - env:
        - name: ANOTHERENV
          value: FOO
        image: nginx
        name: nginx
      - image: sidecar:latest
        name: sidecar
      volumes:
      - gcePersistentDisk:
          pdName: nginx-persistent-storage
        name: nginx-persistent-storage
`)
}

func TestSimpleMultiplePatches(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK("base", `
namePrefix: b-
commonLabels:
  team: foo
resources:
- deployment.yaml
- service.yaml
configMapGenerator:
- name: configmap-in-base
  literals:
  - foo=bar
`)
	th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: nginx-persistent-storage
          mountPath: /tmp/ps
      - name: sidecar
        image: sidecar:latest
      volumes:
      - configMap:
          name: configmap-in-base
        name: configmap-in-base
`)
	th.WriteF("base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - port: 80
`)
	th.WriteK("overlay", `
namePrefix: a-
commonLabels:
  env: staging
patchesStrategicMerge:
- deployment-patch1.yaml
- deployment-patch2.yaml
resources:
- ../base
configMapGenerator:
- name: configmap-in-overlay
  literals:
  - hello=world
`)
	th.WriteF("overlay/deployment-patch1.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        env:
        - name: ENVKEY
          value: ENVVALUE
      volumes:
      - name: nginx-persistent-storage
        gcePersistentDisk:
          pdName: nginx-persistent-storage
      - configMap:
          name: configmap-in-overlay
        name: configmap-in-overlay
`)
	th.WriteF("overlay/deployment-patch2.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        env:
        - name: ANOTHERENV
          value: FOO
`)
	m := th.Run("overlay", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    env: staging
    team: foo
  name: a-b-nginx
spec:
  selector:
    matchLabels:
      env: staging
      team: foo
  template:
    metadata:
      labels:
        env: staging
        team: foo
    spec:
      containers:
      - env:
        - name: ANOTHERENV
          value: FOO
        - name: ENVKEY
          value: ENVVALUE
        image: nginx:latest
        name: nginx
        volumeMounts:
        - mountPath: /tmp/ps
          name: nginx-persistent-storage
      - image: sidecar:latest
        name: sidecar
      volumes:
      - gcePersistentDisk:
          pdName: nginx-persistent-storage
        name: nginx-persistent-storage
      - configMap:
          name: a-configmap-in-overlay-dc6fm46dhm
        name: configmap-in-overlay
      - configMap:
          name: a-b-configmap-in-base-798k5k7g9f
        name: configmap-in-base
---
apiVersion: v1
kind: Service
metadata:
  labels:
    env: staging
    team: foo
  name: a-b-nginx
spec:
  ports:
  - port: 80
  selector:
    env: staging
    team: foo
---
apiVersion: v1
data:
  foo: bar
kind: ConfigMap
metadata:
  labels:
    env: staging
    team: foo
  name: a-b-configmap-in-base-798k5k7g9f
---
apiVersion: v1
data:
  hello: world
kind: ConfigMap
metadata:
  labels:
    env: staging
  name: a-configmap-in-overlay-dc6fm46dhm
`)
}

func makeCommonFilesForMultiplePatchTests(th kusttest_test.Harness) {
	th.WriteK("base", `
namePrefix: team-foo-
commonLabels:
  app: mynginx
  org: example.com
  team: foo
commonAnnotations:
  note: This is a test annotation
resources:
  - deployment.yaml
  - service.yaml
configMapGenerator:
- name: configmap-in-base
  literals:
  - foo=bar
`)
	th.WriteF("base/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: nginx-persistent-storage
          mountPath: /tmp/ps
      - name: sidecar
        image: sidecar:latest
      volumes:
      - configMap:
          name: configmap-in-base
        name: configmap-in-base
`)
	th.WriteF("base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
  selector:
    app: nginx
`)
	th.WriteK("overlay/staging", `
namePrefix: staging-
commonLabels:
  env: staging
patchesStrategicMerge:
  - deployment-patch1.yaml
  - deployment-patch2.yaml
resources:
  - ../../base
configMapGenerator:
- name: configmap-in-overlay
  literals:
  - hello=world
`)
}

func TestMultiplePatchesNoConflict(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	makeCommonFilesForMultiplePatchTests(th)
	th.WriteF("overlay/staging/deployment-patch1.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        env:
        - name: ENVKEY
          value: ENVVALUE
      volumes:
      - name: nginx-persistent-storage
        gcePersistentDisk:
          pdName: nginx-persistent-storage
      - configMap:
          name: configmap-in-overlay
        name: configmap-in-overlay
`)
	th.WriteF("overlay/staging/deployment-patch2.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        env:
        - name: ANOTHERENV
          value: FOO
`)
	m := th.Run("overlay/staging", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-nginx
spec:
  selector:
    matchLabels:
      app: mynginx
      env: staging
      org: example.com
      team: foo
  template:
    metadata:
      annotations:
        note: This is a test annotation
      labels:
        app: mynginx
        env: staging
        org: example.com
        team: foo
    spec:
      containers:
      - env:
        - name: ANOTHERENV
          value: FOO
        - name: ENVKEY
          value: ENVVALUE
        image: nginx:latest
        name: nginx
        volumeMounts:
        - mountPath: /tmp/ps
          name: nginx-persistent-storage
      - image: sidecar:latest
        name: sidecar
      volumes:
      - gcePersistentDisk:
          pdName: nginx-persistent-storage
        name: nginx-persistent-storage
      - configMap:
          name: staging-configmap-in-overlay-dc6fm46dhm
        name: configmap-in-overlay
      - configMap:
          name: staging-team-foo-configmap-in-base-798k5k7g9f
        name: configmap-in-base
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-nginx
spec:
  ports:
  - port: 80
  selector:
    app: mynginx
    env: staging
    org: example.com
    team: foo
---
apiVersion: v1
data:
  foo: bar
kind: ConfigMap
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-configmap-in-base-798k5k7g9f
---
apiVersion: v1
data:
  hello: world
kind: ConfigMap
metadata:
  labels:
    env: staging
  name: staging-configmap-in-overlay-dc6fm46dhm
`)
}

func TestNonCommutablePatches(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	makeCommonFilesForMultiplePatchTests(th)
	th.WriteF("overlay/staging/deployment-patch1.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        env:
        - name: ENABLE_FEATURE_FOO
          value: TRUE
      volumes:
      - name: nginx-persistent-storage
        gcePersistentDisk:
          pdName: nginx-persistent-storage
      - configMap:
          name: configmap-in-overlay
        name: configmap-in-overlay
`)
	th.WriteF("overlay/staging/deployment-patch2.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        env:
        - name: ENABLE_FEATURE_FOO
          value: FALSE
`)
	// kyaml doesn't try to detect conflicts in patches
	// (so ENABLE_FEATURE_FOO FALSE wins).
	m := th.Run("overlay/staging", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-nginx
spec:
  selector:
    matchLabels:
      app: mynginx
      env: staging
      org: example.com
      team: foo
  template:
    metadata:
      annotations:
        note: This is a test annotation
      labels:
        app: mynginx
        env: staging
        org: example.com
        team: foo
    spec:
      containers:
      - env:
        - name: ENABLE_FEATURE_FOO
          value: false
        image: nginx
        name: nginx
        volumeMounts:
        - mountPath: /tmp/ps
          name: nginx-persistent-storage
      - image: sidecar:latest
        name: sidecar
      volumes:
      - gcePersistentDisk:
          pdName: nginx-persistent-storage
        name: nginx-persistent-storage
      - configMap:
          name: staging-configmap-in-overlay-dc6fm46dhm
        name: configmap-in-overlay
      - configMap:
          name: staging-team-foo-configmap-in-base-798k5k7g9f
        name: configmap-in-base
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-nginx
spec:
  ports:
  - port: 80
  selector:
    app: mynginx
    env: staging
    org: example.com
    team: foo
---
apiVersion: v1
data:
  foo: bar
kind: ConfigMap
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-configmap-in-base-798k5k7g9f
---
apiVersion: v1
data:
  hello: world
kind: ConfigMap
metadata:
  labels:
    env: staging
  name: staging-configmap-in-overlay-dc6fm46dhm
`)
}

func TestMultiplePatchesWithOnePatchDeleteDirective(t *testing.T) {
	additivePatch := `apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        env:
        - name: SOME_NAME
          value: somevalue
`
	deletePatch := `apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - $patch: delete
        name: sidecar
`
	cases := map[string]struct {
		patch1      string
		patch2      string
		expectError bool
	}{
		"Patch with delete directive first": {
			patch1: deletePatch,
			patch2: additivePatch,
		},
		"Patch with delete directive second": {
			patch1: additivePatch,
			patch2: deletePatch,
		},
	}
	for name := range cases {
		c := cases[name]
		t.Run(name, func(t *testing.T) {
			th := kusttest_test.MakeHarness(t)
			makeCommonFilesForMultiplePatchTests(th)
			th.WriteF("overlay/staging/deployment-patch1.yaml", c.patch1)
			th.WriteF("overlay/staging/deployment-patch2.yaml", c.patch2)
			m := th.Run("overlay/staging", th.MakeDefaultOptions())
			th.AssertActualEqualsExpected(m, `apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-nginx
spec:
  selector:
    matchLabels:
      app: mynginx
      env: staging
      org: example.com
      team: foo
  template:
    metadata:
      annotations:
        note: This is a test annotation
      labels:
        app: mynginx
        env: staging
        org: example.com
        team: foo
    spec:
      containers:
      - env:
        - name: SOME_NAME
          value: somevalue
        image: nginx
        name: nginx
        volumeMounts:
        - mountPath: /tmp/ps
          name: nginx-persistent-storage
      volumes:
      - configMap:
          name: staging-team-foo-configmap-in-base-798k5k7g9f
        name: configmap-in-base
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-nginx
spec:
  ports:
  - port: 80
  selector:
    app: mynginx
    env: staging
    org: example.com
    team: foo
---
apiVersion: v1
data:
  foo: bar
kind: ConfigMap
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-configmap-in-base-798k5k7g9f
---
apiVersion: v1
data:
  hello: world
kind: ConfigMap
metadata:
  labels:
    env: staging
  name: staging-configmap-in-overlay-dc6fm46dhm
`)
		})
	}
}

func TestMultiplePatchesBothWithPatchDeleteDirective(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	makeCommonFilesForMultiplePatchTests(th)
	th.WriteF("overlay/staging/deployment-patch1.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - $patch: delete
        name: sidecar
`)
	th.WriteF("overlay/staging/deployment-patch2.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - $patch: delete
        name: nginx
`)
	// kyaml doesn't fail on conflicts in patches; both containers
	// (nginx and sidecar) are deleted per this patching instruction.
	m := th.Run("overlay/staging", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-nginx
spec:
  selector:
    matchLabels:
      app: mynginx
      env: staging
      org: example.com
      team: foo
  template:
    metadata:
      annotations:
        note: This is a test annotation
      labels:
        app: mynginx
        env: staging
        org: example.com
        team: foo
    spec:
      containers: []
      volumes:
      - configMap:
          name: staging-team-foo-configmap-in-base-798k5k7g9f
        name: configmap-in-base
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-nginx
spec:
  ports:
  - port: 80
  selector:
    app: mynginx
    env: staging
    org: example.com
    team: foo
---
apiVersion: v1
data:
  foo: bar
kind: ConfigMap
metadata:
  annotations:
    note: This is a test annotation
  labels:
    app: mynginx
    env: staging
    org: example.com
    team: foo
  name: staging-team-foo-configmap-in-base-798k5k7g9f
---
apiVersion: v1
data:
  hello: world
kind: ConfigMap
metadata:
  labels:
    env: staging
  name: staging-configmap-in-overlay-dc6fm46dhm
`)
}

// test for #3513
func TestSmpWithDifferentKeysOnDifferentPorts(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK(".", `
resources:
  - resource.yaml
patches:
  - path: patch.yaml
    target:
      kind: StatefulSet
      name: myapp
`)
	th.WriteF("resource.yaml", `
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myapp
spec:
  template:
    spec:
      containers:
        - name: consul
          image: "dashicorp/consul:1.9.1"
          ports:
            - containerPort: 8500
              name: http
            - containerPort: 8501
              name: https
            - containerPort: 8301
              protocol: "TCP"
              name: serflan-tcp
            - containerPort: 8301
              protocol: "UDP"
              name: serflan-udp
            - containerPort: 8302
              name: serfwan
            - containerPort: 8300
              name: server
            - containerPort: 8600
              name: dns-tcp
              protocol: "TCP"
            - containerPort: 8600
              name: dns-udp
              protocol: "UDP"`)
	th.WriteF("patch.yaml", `
kind: StatefulSet
metadata:
  name: myapp
  labels:
    test: label
`)
	m := th.Run(".", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    test: label
  name: myapp
spec:
  template:
    spec:
      containers:
      - image: dashicorp/consul:1.9.1
        name: consul
        ports:
        - containerPort: 8500
          name: http
        - containerPort: 8501
          name: https
        - containerPort: 8301
          name: serflan-tcp
          protocol: TCP
        - containerPort: 8301
          name: serflan-udp
          protocol: UDP
        - containerPort: 8302
          name: serfwan
        - containerPort: 8300
          name: server
        - containerPort: 8600
          name: dns-tcp
          protocol: TCP
        - containerPort: 8600
          name: dns-udp
          protocol: UDP
`)
}

// test for #3616
func TestSmpDeleteOnResource(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK(".", `
resources:
- workloads.yaml
patches:
- patch: |
    apiVersion: monitoring.coreos.com/v1
    kind: PrometheusRule
    metadata:
      name: rule1
    $patch: delete
`)
	th.WriteF("workloads.yaml", `
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    role: alert-rules
  name: rule1
spec:
  groups:
  - name: rabbitmq.rules
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    role: alert-rules
  name: rule2
spec:
  groups:
  - name: rabbitmq.rules
`)
	m := th.Run(".", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    role: alert-rules
  name: rule2
spec:
  groups:
  - name: rabbitmq.rules
`)
}

// test for #3620
func TestPatchPortHasNoProtocol(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK(".", `
resources:
  - service.yaml
patchesStrategicMerge:
  - patch.yaml
`)
	th.WriteF("service.yaml", `
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  ports:
    - port: 30900
      targetPort: 30900
      protocol: TCP
  type: NodePort
`)
	th.WriteF("patch.yaml", `
apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    service: web
spec:
  ports:
    - port: 30900
      targetPort: 30900
  selector:
    service: web
`)
	m := th.Run(".", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Service
metadata:
  labels:
    service: web
  name: web
spec:
  ports:
  - port: 30900
    protocol: TCP
    targetPort: 30900
  selector:
    service: web
  type: NodePort
`)
}

// test for #3620
func TestPatchAddNewServicePort(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK(".", `
resources:
  - service.yaml
patchesStrategicMerge:
  - patch.yaml
`)
	th.WriteF("service.yaml", `
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  ports:
    - port: 30900
      targetPort: 30900
      protocol: TCP
  type: NodePort
`)
	th.WriteF("patch.yaml", `
apiVersion: v1
kind: Service
metadata:
  name: web
  labels:
    service: web
spec:
  ports:
    - port: 30901
      targetPort: 30901
  selector:
    service: web
`)
	m := th.Run(".", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: Service
metadata:
  labels:
    service: web
  name: web
spec:
  ports:
  - port: 30901
    targetPort: 30901
  - port: 30900
    protocol: TCP
    targetPort: 30900
  selector:
    service: web
  type: NodePort
`)
}

// test for #4111
func TestPatchPreservesInternalAnnotations(t *testing.T) {
	th := kusttest_test.MakeHarness(t)
	th.WriteK(".", `
nameSuffix: -abc
resources:
  - fluentd.yaml
patchesJson6902:
  - path: patch.yaml
    target:
      name: fluentd-sa
      kind: ServiceAccount
      version: v1
`)
	th.WriteF("fluentd.yaml", `
apiVersion: v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  template:
    spec:
      containers:
        - image: fluentd:latest
          name: fluentd
      serviceAccountName: fluentd-sa
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd-sa
`)
	th.WriteF("patch.yaml", `
- op: add
  path: /metadata/annotations
  value:
    note: this is a test annotation
`)
	m := th.Run(".", th.MakeDefaultOptions())
	th.AssertActualEqualsExpected(m, `
apiVersion: v1
kind: DaemonSet
metadata:
  name: fluentd-abc
spec:
  template:
    spec:
      containers:
      - image: fluentd:latest
        name: fluentd
      serviceAccountName: fluentd-sa-abc
---
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    note: this is a test annotation
  name: fluentd-sa-abc
`)
}


text:
echo "Checking to see if the installer script has already been run"
if [ -z $EXAMPLE_VAR ]; then
    $EXAMPLE_VAR=1.0.0
else
    echo "Example variable already set to $EXAMPLE_VAR"
fi

# Run tests to determine that the software installed as expected
echo "Testing to make sure that script performed as expected, and basic scenarios work"
if [ -z $EXAMPLE_VAR ]; then
    echo "EXAMPLE_VAR variable was not set as expected"
    exit 1
else
    echo "EXAMPLE_VAR was set properly"
fi


text:
<?php //-->

use Cradle\CommandLine\Index as CommandLine;
use Cradle\Module\Utility\File;

use Aws\S3\S3Client;

/**
 * CLI Deploy
 *
 * @param Request $request
 * @param Response $response
 */
return function ($request, $response) {
    $cdn = cradle('global')->service('s3-main');

    if (!$cdn) {
        CommandLine::warning('CDN is not setup. Check config/services.php. Aborting.');
        return;
    }

    // load s3
    $s3 = S3Client::factory([
        'version' => 'latest',
        'region'  => $cdn['region'], //example ap-southeast-1
        'credentials' => [
            'key'    => $cdn['token'],
            'secret' => $cdn['secret'],
        ]
    ]);

    //get the public path
    $public = cradle('global')->path('public');

    $bower = $request->getStage('include-bower');
    $upload = $request->getStage('include-upload');

    $pattern = '(\.htaccess)|(\.php)|(DS_Store)';

    if(!$request->hasStage('include-bower')) {
        $pattern .= '|(bower_components)';
    }

    if(!$request->hasStage('include-upload')) {
        $pattern .= '|(upload)';
    }

    //get all the files
    $paths = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($public));

    foreach ($paths as $path) {
        //if it's a directory
        if ($path->isDir()) {
            continue;
        }

        //get the file string
        $file = $path->getPathname();

        //there's no point pushing these things
        if (preg_match('/' . $pattern . '/', $file)) {
            continue;
        }

        // if /foo/bar/repo/public/path/to/file, then /path/to/file
        $path = substr($file, strlen($public) + 1);

        //there's no better way to get a mime
        $mime = File::getMimeFromLink($file);

        //open a pipe
        $pipe = fopen($file, 'r');

        print sprintf("\033[36m%s\033[0m", '[cradle] * pushing '.$path);
        print PHP_EOL;

        $s3->putObject(array(
            'Bucket'        => $cdn['bucket'],
            'ACL'           => 'public-read',
            'ContentType'   => $mime,
            'Key'           => $path,
            'Body'          => $pipe,
            'CacheControl'  => 'max-age=43200'
        ));

        if (is_resource($pipe)) {
            fclose($pipe);
        }
    }
};


text:
define([], function() {

  return [
    '../test/unit/casgraph/sha1hasher.test',
    '../test/unit/casgraph/graph.test',
    '../test/unit/casgraph/replicator.test',
    '../test/unit/graphapi.test',
    '../test/unit/geometrygraph.test',
    '../test/unit/geomnode.test',
    '../test/unit/validation.test',
    '../test/unit/mesh.test',
    '../test/unit/variablegraph.test',
    '../test/unit/layers/layertree.test',
  ];

});


text:
package org.apache.flink.graph.library;

import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.graph.Edge;
import org.apache.flink.graph.Graph;
import org.apache.flink.graph.Vertex;
import org.apache.flink.graph.asm.AsmTestBase;
import org.apache.flink.graph.asm.dataset.ChecksumHashCode;
import org.apache.flink.graph.asm.dataset.ChecksumHashCode.Checksum;
import org.apache.flink.graph.generator.SingletonEdgeGraph;
import org.apache.flink.test.util.TestBaseUtils;
import org.apache.flink.types.IntValue;
import org.apache.flink.types.LongValue;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
 * Tests for {@link CommunityDetection}.
 */
public class CommunityDetectionTest extends AsmTestBase {

	@Test
	public void testWithSimpleGraph() throws Exception {
		Graph<IntValue, Long, Double> result = undirectedSimpleGraph
			.mapVertices(v -> (long) v.getId().getValue(),
				new TypeHint<Vertex<IntValue, Long>>(){}.getTypeInfo())
			.mapEdges(e -> (double) e.getTarget().getValue() + e.getSource().getValue(),
				new TypeHint<Edge<IntValue, Double>>(){}.getTypeInfo())
			.run(new CommunityDetection<>(10, 0.5));

		String expectedResult =
			"(0,3)\n" +
			"(1,5)\n" +
			"(2,5)\n" +
			"(3,3)\n" +
			"(4,5)\n" +
			"(5,5)\n";

		TestBaseUtils.compareResultAsText(result.getVertices().collect(), expectedResult);
	}

	@Test
	public void testWithSingletonEdgeGraph() throws Exception {
		Graph<LongValue, Long, Double> result = new SingletonEdgeGraph(env, 1)
			.generate()
			.mapVertices(v -> v.getId().getValue(),
				new TypeHint<Vertex<LongValue, Long>>(){}.getTypeInfo())
			.mapEdges(e -> 1.0,
				new TypeHint<Edge<LongValue, Double>>(){}.getTypeInfo())
			.run(new CommunityDetection<>(10, 0.5));

		String expectedResult =
			"(0,0)\n" +
			"(1,1)\n";

		TestBaseUtils.compareResultAsText(result.getVertices().collect(), expectedResult);
	}

	@Test
	public void testWithEmptyGraphWithVertices() throws Exception {
		emptyGraphWithVertices
			.mapVertices(v -> 0L,
				new TypeHint<Vertex<LongValue, Long>>(){}.getTypeInfo())
			.mapEdges(e -> 0.0,
				new TypeHint<Edge<LongValue, Double>>(){}.getTypeInfo())
			.run(new CommunityDetection<>(10, 0.5));
	}

	@Test
	public void testWithEmptyGraphWithoutVertices() throws Exception {
		emptyGraphWithoutVertices
			.mapVertices(v -> 0L,
				new TypeHint<Vertex<LongValue, Long>>(){}.getTypeInfo())
			.mapEdges(e -> 0.0,
				new TypeHint<Edge<LongValue, Double>>(){}.getTypeInfo())
			.run(new CommunityDetection<>(10, 0.5));
	}

	@Test
	public void testWithRMatGraph() throws Exception {
		Graph<LongValue, Long, Double> result = undirectedRMatGraph(8, 4)
			.mapVertices(v -> v.getId().getValue(),
				new TypeHint<Vertex<LongValue, Long>>(){}.getTypeInfo())
			.mapEdges(e -> (double) e.getTarget().getValue() - e.getSource().getValue(),
				new TypeHint<Edge<LongValue, Double>>(){}.getTypeInfo())
			.run(new CommunityDetection<>(10, 0.5));

		Checksum checksum = new ChecksumHashCode<Vertex<LongValue, Long>>()
			.run(result.getVertices())
			.execute();

		assertEquals(184, checksum.getCount());
		assertEquals(0x00000000000cdc96L, checksum.getChecksum());
	}
}


text:
static const UINT kStatusIconMessage = WM_APP + 1;

namespace {
// |kBaseIconId| is 2 to avoid conflicts with plugins that hard-code id 1.
const UINT kBaseIconId = 2;

UINT ReservedIconId(StatusTray::StatusIconType type) {
  return kBaseIconId + static_cast<UINT>(type);
}

// See http://crbug.com/412384.
void TraceSessionEnding(LPARAM lparam) {
  browser_watcher::ExitFunnel funnel;
  if (!funnel.Init(chrome::kBrowserExitCodesRegistryPath,
                   base::GetCurrentProcessHandle())) {
    return;
  }

  // This exit path is the prime suspect for most our unclean shutdowns.
  // Trace all the possible options to WM_ENDSESSION. This may result in
  // multiple events for a single shutdown, but that's fine.
  funnel.RecordEvent(L"TraybarEndSession");

  if (lparam & ENDSESSION_CLOSEAPP)
    funnel.RecordEvent(L"ES_CloseApp");
  if (lparam & ENDSESSION_CRITICAL)
    funnel.RecordEvent(L"ES_Critical");
  if (lparam & ENDSESSION_LOGOFF)
    funnel.RecordEvent(L"ES_Logoff");
  const LPARAM kKnownBits =
      ENDSESSION_CLOSEAPP | ENDSESSION_CRITICAL | ENDSESSION_LOGOFF;
  if (lparam & ~kKnownBits)
    funnel.RecordEvent(L"ES_Other");
}

}  // namespace

// Default implementation for StatusTrayStateChanger that communicates to
// Exporer.exe via COM.  It spawns a background thread with a fresh COM
// apartment and requests that the visibility be increased unless the user
// has explicitly set the icon to be hidden.
class StatusTrayStateChangerProxyImpl : public StatusTrayStateChangerProxy,
                                        public base::NonThreadSafe {
 public:
  StatusTrayStateChangerProxyImpl()
      : pending_requests_(0),
        worker_thread_("StatusIconCOMWorkerThread"),
        weak_factory_(this) {
    worker_thread_.init_com_with_mta(false);
  }

  virtual void EnqueueChange(UINT icon_id, HWND window) override {
    DCHECK(CalledOnValidThread());
    if (pending_requests_ == 0)
      worker_thread_.Start();

    ++pending_requests_;
    worker_thread_.message_loop_proxy()->PostTaskAndReply(
        FROM_HERE,
        base::Bind(
            &StatusTrayStateChangerProxyImpl::EnqueueChangeOnWorkerThread,
            icon_id,
            window),
        base::Bind(&StatusTrayStateChangerProxyImpl::ChangeDone,
                   weak_factory_.GetWeakPtr()));
  }

 private:
  // Must be called only on |worker_thread_|, to ensure the correct COM
  // apartment.
  static void EnqueueChangeOnWorkerThread(UINT icon_id, HWND window) {
    // It appears that IUnknowns are coincidentally compatible with
    // scoped_refptr.  Normally I wouldn't depend on that but it seems that
    // base::win::IUnknownImpl itself depends on that coincidence so it's
    // already being assumed elsewhere.
    scoped_refptr<StatusTrayStateChangerWin> status_tray_state_changer(
        new StatusTrayStateChangerWin(icon_id, window));
    status_tray_state_changer->EnsureTrayIconVisible();
  }

  // Called on UI thread.
  void ChangeDone() {
    DCHECK(CalledOnValidThread());
    DCHECK_GT(pending_requests_, 0);

    if (--pending_requests_ == 0)
      worker_thread_.Stop();
  }

 private:
  int pending_requests_;
  base::Thread worker_thread_;
  base::WeakPtrFactory<StatusTrayStateChangerProxyImpl> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(StatusTrayStateChangerProxyImpl);
};

StatusTrayWin::StatusTrayWin()
    : next_icon_id_(1),
      atom_(0),
      instance_(NULL),
      window_(NULL) {
  // Register our window class
  WNDCLASSEX window_class;
  base::win::InitializeWindowClass(
      chrome::kStatusTrayWindowClass,
      &base::win::WrappedWindowProc<StatusTrayWin::WndProcStatic>,
      0, 0, 0, NULL, NULL, NULL, NULL, NULL,
      &window_class);
  instance_ = window_class.hInstance;
  atom_ = RegisterClassEx(&window_class);
  CHECK(atom_);

  // If the taskbar is re-created after we start up, we have to rebuild all of
  // our icons.
  taskbar_created_message_ = RegisterWindowMessage(TEXT("TaskbarCreated"));

  // Create an offscreen window for handling messages for the status icons. We
  // create a hidden WS_POPUP window instead of an HWND_MESSAGE window, because
  // only top-level windows such as popups can receive broadcast messages like
  // "TaskbarCreated".
  window_ = CreateWindow(MAKEINTATOM(atom_),
                         0, WS_POPUP, 0, 0, 0, 0, 0, 0, instance_, 0);
  gfx::CheckWindowCreated(window_);
  gfx::SetWindowUserData(window_, this);
}

StatusTrayWin::~StatusTrayWin() {
  if (window_)
    DestroyWindow(window_);

  if (atom_)
    UnregisterClass(MAKEINTATOM(atom_), instance_);
}

void StatusTrayWin::UpdateIconVisibilityInBackground(
    StatusIconWin* status_icon) {
  if (!state_changer_proxy_.get())
    state_changer_proxy_.reset(new StatusTrayStateChangerProxyImpl);

  state_changer_proxy_->EnqueueChange(status_icon->icon_id(),
                                      status_icon->window());
}

LRESULT CALLBACK StatusTrayWin::WndProcStatic(HWND hwnd,
                                              UINT message,
                                              WPARAM wparam,
                                              LPARAM lparam) {
  StatusTrayWin* msg_wnd = reinterpret_cast<StatusTrayWin*>(
      GetWindowLongPtr(hwnd, GWLP_USERDATA));
  if (msg_wnd)
    return msg_wnd->WndProc(hwnd, message, wparam, lparam);
  else
    return ::DefWindowProc(hwnd, message, wparam, lparam);
}

LRESULT CALLBACK StatusTrayWin::WndProc(HWND hwnd,
                                        UINT message,
                                        WPARAM wparam,
                                        LPARAM lparam) {
  if (message == taskbar_created_message_) {
    // We need to reset all of our icons because the taskbar went away.
    for (StatusIcons::const_iterator i(status_icons().begin());
         i != status_icons().end(); ++i) {
      StatusIconWin* win_icon = static_cast<StatusIconWin*>(*i);
      win_icon->ResetIcon();
    }
    return TRUE;
  } else if (message == kStatusIconMessage) {
    StatusIconWin* win_icon = NULL;

    // Find the selected status icon.
    for (StatusIcons::const_iterator i(status_icons().begin());
         i != status_icons().end();
         ++i) {
      StatusIconWin* current_win_icon = static_cast<StatusIconWin*>(*i);
      if (current_win_icon->icon_id() == wparam) {
        win_icon = current_win_icon;
        break;
      }
    }

    // It is possible for this procedure to be called with an obsolete icon
    // id.  In that case we should just return early before handling any
    // actions.
    if (!win_icon)
      return TRUE;

    switch (lparam) {
      case TB_INDETERMINATE:
        win_icon->HandleBalloonClickEvent();
        return TRUE;

      case WM_LBUTTONDOWN:
      case WM_RBUTTONDOWN:
      case WM_CONTEXTMENU:
        // Walk our icons, find which one was clicked on, and invoke its
        // HandleClickEvent() method.
        gfx::Point cursor_pos(
            gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
        win_icon->HandleClickEvent(cursor_pos, lparam == WM_LBUTTONDOWN);
        return TRUE;
    }
  } else if (message == WM_ENDSESSION) {
    // If Chrome is in background-only mode, this is the only notification
    // it gets that Windows is exiting. Make sure we shutdown in an orderly
    // fashion.
    TraceSessionEnding(lparam);
    chrome::SessionEnding();
  }
  return ::DefWindowProc(hwnd, message, wparam, lparam);
}

StatusIcon* StatusTrayWin::CreatePlatformStatusIcon(
    StatusTray::StatusIconType type,
    const gfx::ImageSkia& image,
    const base::string16& tool_tip) {
  UINT next_icon_id;
  if (type == StatusTray::OTHER_ICON)
    next_icon_id = NextIconId();
  else
    next_icon_id = ReservedIconId(type);

  StatusIcon* icon =
      new StatusIconWin(this, next_icon_id, window_, kStatusIconMessage);

  icon->SetImage(image);
  icon->SetToolTip(tool_tip);
  return icon;
}

UINT StatusTrayWin::NextIconId() {
  UINT icon_id = next_icon_id_++;
  return kBaseIconId + static_cast<UINT>(NAMED_STATUS_ICON_COUNT) + icon_id;
}

void StatusTrayWin::SetStatusTrayStateChangerProxyForTest(
    scoped_ptr<StatusTrayStateChangerProxy> proxy) {
  state_changer_proxy_ = proxy.Pass();
}

StatusTray* StatusTray::Create() {
  return new StatusTrayWin();
}